.htaccess では RewriteRule の [L] フラグが効かない

リクエスト URL の書き換えやリダイレクト処理に便利な mod_rewrite モジュールが思い通りに動かない。そのような時に確認しておきたい基本事項。

目次
  1. mod_rewrite モジュールの挙動の違い
    1. 繰り返される RewriteRule
    2. 止められない [L] フラグ
  2. 参考

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] フラグは機能しない。