[Apache] mod_rewriteの使い方・.htaccessでリダイレクトする
サイト引っ越し時の URL の書き換えや、リダイレクトさせたい時に使うのが「 mod_rewrite
モジュール」。
WordPress とか XAMPP の「 .htaccess
」ファイルに書いてあるやつで、たまに使うけど、「 RewriteRule
」とか「 RewriteCond
」とか、よくわからないままだったので書かれている意味を調べた。
mod_rewrite とは
Apache のモジュールで、 URL の書き換え・リダイレクト処理のルールを設定するもの
「 .htaccess
」や「 httpd.conf
」という Apache 設定ファイルに記述する(ここでは「 .htaccess
」への記述方法を解説)
記述にはルールがあり、書き方を間違えると 500 エラーが発生する
ルール
コメントアウト記号は「#」
文字コード UTF-8 ( BOM 無し)
最終行には空行を入れる
サンプル
# こんなやつ
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteBase /hoge/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /hoge/index.php [L]
</ifModule>
RewriteEngine
「On」:mod_rewrite
を有効にする
「Off」:無効にする
mod_rewrite
が利用できない場合、エラーが発生するので、if
文で mod_rewrite
が使えるなら「On」という記述を書く
<ifModule mod_rewrite.c>
RewriteEngine On
#・・・処理・・・
</ifModule>
RewriteBase
「リダイレクト先」のベース URL を設定する。(リダイレクト元の URL とはなんら関係ないことに注意)
この記述がない場合は、 .htaccess
が置いてあるディレクトリが指定される
[ RewriteBase /
]と記述すると、どのディレクトリに .htaccess
が置いてあってもドキュメントルートからのパスになる
RewriteCond
RewriteRule
を適用するかの条件を定義する( if
文のようなもの)
%{変数名}
を参照して、それが指定した条件パターンと一致していれば(または一致していなければ)、次の条件( RewriteRule
)を実行する
RewriteRule
の前に書く
使用できる変数名(一部)
変数名 | 値 | |
---|---|---|
HTTP ヘッダ | HTTP_USER_AGENT | ユーザーエージェント |
HTTP_HOST | サーバーホスト名(ドメイン名) | |
HTTP_COOKIE | クッキー情報 | |
HTTP_REFERER | 参照元URL | |
HTTP_ACCEPT | MIMEタイプ(image/webpとか) | |
HTTP_PROXY_CONNECTION | プロキシサーバー経由か否か | |
HTTP_FORWARDED | 経由してきたプロキシサーバーの情報 | |
サーバー内部変数 | SERVER_ADMIN | サーバーやサイト管理者の情報(メアドとか) |
DOCUMENT_ROOT | ドキュメントルートのパス(ルートディレクトリ) | |
SERVER_NAME | サーバー名 | |
SERVER_ADDR | サーバーのIPアドレス | |
SERVER_PORT | サーバーのポート番号 | |
SERVER_PROTOCOL | サーバープロトコル | |
SERVER_SOFTWARE | サーバーソフトウェア名(Apacheとか) | |
コネクション & リクエスト | REMOTE_ADDR | ホストのIPアドレス |
DOCUMENT_ROOT | ドキュメントルートのパス(ルートディレクトリ) | |
REMOTE_HOST | リモートホスト名(ドメイン) | |
QUERY_STRING | クエリ文字列 | |
SCRIPT_FILENAME | スクリプトファイル名とパス | |
REQUEST_METHOD | リクエストがGETかPOSTか | |
mode_rewrite 用特殊 | REQUEST_FILENAME | ファイルシステムのファイルパス(/var/www/html/wordpress/.... ) |
HTTPS | リクエストが「https 」なら「ON」、「http 」なら「OFF」 | |
REQUEST_URI | リクエストURI([http://hoge.com/test/abc.php ] なら [/test/abc.php ] 頭にスラッシュがつく) |
条件パターン
正規表現や記号を用いて条件を指定するパターン | 意味 |
---|---|
! | 否定 |
< | 大きい |
> | 未満 |
= | 等しい |
=< | 以上 |
=> | 以下 |
-d | ディレクトリが存在するか |
-f | ファイルが存在するか |
-s | ファイルが存在し、かつサイズが0より大きい |
-l, -H, -L | シンボリックリンクか |
-eq | = と同じ |
-ge | <= と同じ |
-gt | < と同じ |
-le | >= と同じ |
-lt | > と同じ |
-U | アクセス可能な有効なURLか |
使用できるフラグ
[OR] | RewriteCond は、RewriteRule の前に書くもので、複数記述することができる複数記述した場合、全部一致( AND )か、複数あるうちの1つが一致すればいい(OR )のかを指定するフラグに何も書かない場合は AND 、フラグに[OR] と書くとOR 条件となる |
---|---|
[NC] | no caseのこと。大文字と小文字を区別しない |
RewriteRule
リダイレクト、置き換えのルールを定義する
リクエスト URL とパターンがマッチすれば、置換対象に置き換えられる
上から順に処理されていく(記述する順番に注意)
パターンには、正規表現を書く
置換対象には、リダイレクト先などを書く。置換対象に相対パス(スラッシュなし)を書くと、 RewriteBase
がパスとなる。
例えば、 RewriteBase
が [hoge
] で、置換対象に [app/index.html
] (相対パス)と書くと、生成される URL は [/hoge/app/index.html
] となる。
[/app/index.html
]とするとそのまま、何も付加されない。
パターンとのマッチング方法は、リクエストされた URL から、 .htaccess
が置いてあるディレクトリまでのパス(最後のスラッシュまで)を除いたものが、パターンと比較される。
例えば、 [test
] というディレクトリに .htaccess
があって、 [http://hoge.com/test/abc.php
] でリクエストがあった場合、 [abc.php
] がパターンと比較される。
フラグ
RewriteRule
の第 3 引数に記述する。省略可。
フラグ | 意味 |
---|---|
[R] | 指定した先にリダイレクトする。[R] (値省略時)は [R=302] となる例)[R=301] 301 にリダイレクト* 301 は恒久的なリダイレクト、302 は一次的なリダイレクト |
[L] | last これ以降のルールは実行されない。ここで終了[R] を書くときは、必ず[L] を一緒に書く例) [R=301,L] |
[F] | HTTPレスポンス403 (Forbidden = アクセス権限がない)を返す |
[G] | HTTPレスポンス410 (Gone = 指定ファイルがない)を返す |
[C] | ルールを連続して処理する。1のルールを通過後、2のルール、3のルール…とチェーンしていく |
[N] | >next 置換後のURLに対し、ルールを再実行(ループ処理のような者) |
[NC] | no case 大文字小文字を区別しない |
[NE] | noescape URLエスケープしない(通常はURLエスケープされる) |
[NS] | 現在のリクエストがサブリクエストである場合、ルールをスキップ |
[S]S=num | skip Sで指定した数だけ後続のルールをスキップする |
[T]T=MIME-type | >ターゲットファイルのMIMEタイプを、強制的に指定したMIMEタイプに置き換える 例)[T=image/webp] |
[E]E=VAR:VAL,!VAR | 環境変数の値をセットする。(環境変数VARの値をVALにする) [E=!VAR]だとVARが削除される 例)[E=accept:1] 変数acceptの値を1にする |
サンプルの解説
最初にあげたサンプルの意味を解説
#上のサンプルと一緒のコード
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteBase /hoge/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /hoge/index.php [L]
</ifModule>
RewriteRule ^index\.php$ - [L]
「^」は正規表現で、行頭を意味する
「$」は正規表現で、行末を意味する
「-」は正規表現で、書き換えをしないという意味
よって、 [index.php
] でリクエストが来たら、そのまま [index.php
] が呼び出される
フラグが [L]
なので、ルールはここで終了。後続処理は行われない
RewriteCond %{REQUEST_FILENAME} !-f
7 行目:
RewriteCond %{REQUEST_FILENAME} !-d
リクエストされたファイルが存在しない、かつ( AND
)リクエストされたディレクトリが存在しない場合、 RewriteRule . /hoge/index.php [L]
が実行される。
RewriteRule . /hoge/index.php [L]
「.」は正規表現で、任意の 1 文字を意味する
この場合、「.」は「どんなリクエストでも」という解釈となり、リクエストが存在するファイルやディレクトリではない場合、全て [/hoge/index.php
] に置き換わる(内部転送)
ちなみに、 [RewriteBase /hoge/
] としているが、 [RewriteRule . /hoge/index.php [L]
] の置換対象( /hoge/index.php
)の頭にスラッシュ( /
)があるので、 RewriteBase
のパスは適用されない( hoge/hoge/index.php
とはならない)