[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_ACCEPTMIMEタイプ(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

リダイレクト、置き換えのルールを定義する
書式: 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=numskip 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>
5行目:RewriteRule ^index\.php$ - [L]

「^」は正規表現で、行頭を意味する
「$」は正規表現で、行末を意味する
「-」は正規表現で、書き換えをしないという意味
よって、[index.php]でリクエストが来たら、そのまま[index.php]が呼び出される
フラグが[L]なので、ルールはここで終了。後続処理は行われない

6行目:RewriteCond %{REQUEST_FILENAME} !-f
7行目:RewriteCond %{REQUEST_FILENAME} !-d

リクエストされたファイルが存在しない、かつ(AND)リクエストされたディレクトリが存在しない場合、RewriteRule . /hoge/index.php [L]が実行される

8行目:RewriteRule . /hoge/index.php [L]

「.」は正規表現で、任意の1文字を意味する
この場合、「.」は「どんなリクエストでも」という解釈となり、リクエストが存在するファイルやディレクトリではない場合、全て[/hoge/index.php]に置き換わる(内部転送)

ちなみに、[RewriteBase /hoge/]としているが、[RewriteRule . /hoge/index.php [L]]の置換対象(/hoge/index.php)の頭にスラッシュ(/)があるので、RewriteBaseのパスは適用されない(hoge/hoge/index.phpとはならない)

Posted by Agopeanuts