リダイレクト(.htaccess等)

リダイレクトについて

リダイレクトには、.htaccess、javascript、PHPの3パータンの方法がある。

.htaccessを利用したリダイレクト

<!-- .htaccess内 -->
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} (iPhone|iPod|Android|BlackBerry|Windows.Phone) [NC]
RewriteCond %{QUERY_STRING} !mode=pc
RewriteRule ^$ https://kanri.nkdesk.com/iphone/ [R,L]
</IfModule>

apacheの命令、mod_rewriteを使用するとモバイル端末はA、PCはBというように端末でリダイレクト先を振り分けることができる。 そして、ifmoduleでmod_rewriteが利用できるかをまず確認し、サーバーがこのモジュールを利用できればその中身を実行するが利用できなければエラーを返す。

上から順番に実行され、改行がandの意味。。

RewriteenginONはmod_rewriteの書き換え機能をONにするという記述、RewriteBaseでベースを/にする(.htaccessの設置してある階層。/abcならabcフォルダの全てのファイル)。でiponeまたはipod…(小文字大文字区別なし)端末でのアクセス→改行(and)→(query_string)?以下がmode=pcでないサイトの時、問答無用にhttps://kanri.nkdesk.com/iphone/にリダイレクト[R]しろというもの。rewitebeseは初期値が/だから別に書かなくてもいい。

(RewriteRule データ リダイレクト先)のりダイレクト先をURLで指定すると、ブラウザのURLが書き換えられてそこに飛ばされる。この方法はログが増えるから推奨されない。

.htaccessは、以下の表(https://webtech.akijapan.com/htaccess/rewrite.phtmlより引用)がわかりやすい。

ディレクティブと書式 初期値 説明
RewriteEngine on/off off 書き換えの可否を設定。
RewriteOptions inherit - inherit : 現在の設定値を親ディレクトリの設定値から強制的に継承する。
RewriteBase / / 書き換えのベースとなるパス(ベースが明白な場合は不要)。
RewriteCond テスト文字列 条件 パターン。 - 条件によるテスト文字列とパターンの比較。
RewriteRule パターン 置換対象。 - パターンを置換対象で置き換える。

オプション

[R] 強制的にリダイレクト (Redirect) する。
[R=301] : 永久的に移動。HTTP レスポンスの「301 : Moved Permanently」を返します。。
[R=302] : 一時的な移動。HTTP レスポンスの「302 : Moved Temporarily」を返します、デフォルト。
[F] 強制的にアクセス禁止 (Forbidden) にする。
HTTP レスポンスの「403 : Forbidden」を返します。
[G] 強制的に消去済み (Gone) にする。
HTTP レスポンスの「410 : Gone」を返します。
もはや存在しないページを消去済みとしてマークします。
[L] 書き換えが行われたら終了 (Last) にする。
現在の書き換え後の URL が後続のルール によってそれ以上書き換えられることを防止します。
[NC] パターンについて、文字の大小を区別しない(No Case)。
つまり、”A-Z” と “a-z” は区別されません。
[OR] または。

正規表現

文字 説明
! 否定。
. 任意の1文字。
[ ] 括弧内のいずれかの文字。
[^ ] 括弧内のいずれかの文字以外。
| または。
? 直前の文字の0回または1回の繰り返し
* 直前の文字の0回以上の繰り返し。
+ 直前の文字の1回以上の繰り返し。
( ) 選択範囲の境界を明示する、もしくは後方参照を作成する。
^ 行頭。
$ 行末。
$n (0 <= n <= 9) 後方参照。 n番目の( )内の値が入ります。
%{ } サーバ変数の取得。
\ (日本語環境では円マーク)正規表現の特殊文字をエスケープする。

サーバ変数

変数名 説明
HTTP_USER_AGENT ブラウザの種類とバージョン。
HTTP_REFERER 参照元の URL 。
HTTP_COOKIE 設定されているクッキー情報。
HTTP_FORWARDED プロキシサーバ情報。
HTTP_HOST 接続要求しているホスト名。
HTTP_PROXY_CONNECTION 接続先プロキシサーバとの接続状態。
HTTP_ACCEPT ブラウザが認識可能なデータ形式。
DOCUMENT_ROOT サイトのルートディレクトリ。
SERVER_ADMIN サーバ管理者のメールアドレス情報。
SERVER_NAME サーバのホスト名、ドメイン名、またはIPアドレス情報。
SERVER_ADDR サーバのIPアドレス。
SERVER_PORT 送信に使われたサーバのポート番号。
SERVER_PROTOCOL 送信に使われたプロトコルの名前とレビジョン情報。
SERVER_SOFTWARE 起動したサーバソフトウエアの名前とバージョン情報。
REMOTE_ADDR リモートホストのIPアドレス情報。
REMOTE_HOST リモートホストのドメイン名。
REMOTE_USER ユーザの認証名。
REMOTE_IDENT リモートホストのユーザ名。
REQUEST_METHOD リクエストを送信した方法。
REQUEST_URI リクエストされたURI。
SCRIPT_FILENAME 現在実行しているスクリプト名。
PATH_INFO クライアントから送られるパス情報。
QUERY_STRING URL に付加して渡された “?” 以降の文字列。
AUTH_TYPE ユーザを認証するときに使用する認証方法。
TIME_YEAR サーバのシステム日付・年
TIME_MON サーバのシステム日付・月
TIME_DAY サーバのシステム日付・日
TIME_HOUR サーバのシステム日付・時
TIME_MIN サーバのシステム日付・分
TIME_SEC サーバのシステム日付・秒
TIME_WDAY サーバのシステム日付・曜日
TIME サーバのシステム日付・Unix タイムスタンプ。
<!-- .htaccess内 -->
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !(^/iphone/)
RewriteCond %{HTTP_USER_AGENT} (iPhone|iPod|Android|BlackBerry|Windows.Phone) [NC]
RewriteCond %{QUERY_STRING} !mode=pc
RewriteRule ^(.*)$ iphone/$1 [R=301,L]
</IfModule>

そこで、正規表現を作り変えて、https://kanri.nkdesk.com/以下のファイルのうち、先頭から最後まで間で0文字以上の文字の繰り返しをiphoneフォルダ直下に置き換え、301でリダイレクトさせる。

上の表から、^は先頭、$は最後、()はグループ、.*は0文字以上の羅列、R=301はブラウザのURLも書き換えて永久リダイレクトであることがわかる。

$1は()内を前方参照するから、https://kanri.nkdesk.com/aiueo/hoge.htmlであればhttps://kanri.nkdesk.com/iphone/aiueo/hoge.htmlに変わるということ。

これだけだと、無限ループに陥って、リダイレクトが多すぎとかそんな感じのエラーになるから、!(^/iphone/)という、iphoneの文字が入っていれば、それ以降の命令を実行させないようにしておく。これにより、https://kanri.nkdesk.com/iphone/iphone/iphone・・・のような無限ループを防げる。

正規表現では、 「^(.*)(\.[a-z]+)$ iphone/$1/$2」のようにグループ化した表現を2つ並べて$1に(.*)、$2に(\.[a-z]+)というように続けて(1文字を分割して)代入することも可能。「\.」は「.」がメタ文字なのでバックスラッシュでエスケープしているだけでその文字自体に意味はない。この正規表現なら、0文字以上の繰り返しを$1に、そこで一旦切って、ドットからa~zの1文字以上の繰り返しまでを$2に入れろという意味。

サイト全体をリダイレクトさせるには

補足として、サイト全体をモバイル、PCサイトを含めて、そのままリダイレクトさせたいのであれば、下記3パターンを使う。

.htaccessファイルを置いたディレクトリの下層ディレクトリに対しても同様な効果が適用されるが、下層にもし別の.htaccessファイルが置いてあれば、そっちが優先される。

<!-- .htaccess内 -->
RedirectMatch 301 .* https://www.nkdesk.com/
Redirect permanent /first/ https://nkdesk.com/second/
Redirect permanent / https://www.nkdesk.com/

1行目は、サイト全体(前頁)を、引越し先のトップページに飛ばす方法で、古いサイトのトップページだけ残して、その階層にhtaccessファイルを置いて上を1行書いておけば、新しいサイトのトップに飛んでくれる。(サイトの階層が変わっているサイト向け)

2行目は、ディレクトリ構造を生かしたまま、かつフォルダ名を変えてしまった場合に、firstから以下全部をsecondに変えて飛ばす。(サイトの階層のフォルダ名だけ変えてしまったサイト向け)

3行目は、2行目のフォルダ名を変えない、つまりそのままURLだけ変えてリダイレクトさせるパターンで、階層が維持されたままリダイレクトされる。(ただのURLだけ変える移転ならこれを使う)

正規表現は、通常バックスラッシュ(デリミタ)で最初と最後を囲むけど、囲まなくても動くみたいね。

リダイレクトはデフォは302だけど、イコールをつけて301を指定することもできます。301は永久移動、302は一時移動ということで、サイトの移転であれば301を使うべきだが、モバイル端末へのリダイレクトは301でも302でもいいらしい。

また、サーバー変数の補足として、URIというのは、URLと同じものと考えてよさそう。http/kanri.nkdesk.com/iphone/aaa.htmlというURLがあったとして、$_SERVER["SERVER_NAME"]でkanri.nkdesk.comが、$_SERVER["PHP_SELF"]で/iphone/aaa.htmlが取得できる。

コメントor補足情報orご指摘あればをお願いします。

(件名or本文内でキーワード検索できます)



  • << 前のページ
  • 次のページ >>
ページトップへ