.htaccess では RewriteRule の [L] フラグが効かない
リクエスト URL の書き換えやリダイレクト処理に便利な mod_rewrite モジュールが思い通りに動かない。そのような時に確認しておきたい基本事項。
mod_rewrite モジュールの挙動の違い
レンタルサーバ環境では通常、httpd.conf などの設定ファイルの編集は行えません。そのため、サーバ動作の制御には .htaccess ファイルを使用することが多いと思います。
例えば、レンタルサーバを利用して制作したサイトで、動的アドレスを静的アドレスに変換するような場合。そこで使われる Apache の mod_rewrite モジュールは、設定ファイルではなく .htaccess に記述することもできます。しかし、httpd.conf と違った挙動になることもあるので注意が必要です。
繰り返される RewriteRule
次のような mod_rewrite モジュールのコードがあるとします。
RewriteRule 1.php /2.php
RewriteRule 2.php /3.php
RewriteRule 3.php /4.php
1.php のリクエストで、最終的には 4.php が返される。この挙動は、.htaccess でも httpd.conf でも同様です。
しかし次のコードの場合は違いが生まれます。
RewriteRule 1.php /2.php
RewriteRule 3.php /4.php
RewriteRule 2.php /3.php
1.php の最終的な出力は、今度は次のようになります。
- .htaccess
- 4.php
- httpd.conf
- 3.php
.htaccess の場合、書き換え後には最初に戻ってまたマッチングを始めます。最終行で 3.php に書き換えてもそこで終了せず、再び上から適用を試み、その結果 4.php にへの書き換えが行われる。ルールにマッチしなくなるまで繰り返されるわけです。
他方、httpd.conf は、最終行の書き換えで処理を終えています。
止められない [L] フラグ
RewriteRule のオプションのひとつに、[L] フラグがあります。これは last を意味し、条件にマッチしたらそれ以降のルールは適用しないようにするためのものです。
先ほどのコードに [L] フラグを書き足してみます。
RewriteRule 1.php /2.php [L]
RewriteRule 3.php /4.php
RewriteRule 2.php /3.php
1.php の出力はこうなります。
- .htaccess
- 4.php
- httpd.conf
- 2.php
httpd.conf は [L] フラグの機能通りの振る舞いをしていますが、.htaccess は相変わらず 4.php のままになっています。
これはなぜかというと、.htaccess では [L] フラグがそもそも有効にならないからです。フラグは無視され、以降のルールも適用対象に。前述の通り、書き換えては最初に戻り、最終的に 4.php に落ち着いたというわけです。
参考
今日学んだこと
.htaccess ファイルでは、RewriteRule ディレクティブの [L] フラグは機能しない。