2015年9月26日土曜日

.htaccess と RewiteRule

Apache の RewriteRule を設定していて結構はまったのでメモ。

RewriteRule を .htaccess に書く場合、最も深いサブディレクトリにある .htaccess のルールから適用され、その後親ディレクトリの .htaccess のルールが適用される(この動作は RewriteOption で変更可能)。

でも、やってみたら親ディレクトリの .htaccess が全く効いていないっぽい。ていうか、DocumentRoot にのみ .htaccess を置いても無視された。

原因は Alias を使って子ディレクトリを別のディレクトリに向けていたことだった模様。

どいうことかというと、RewriteRule が適用される .htaccess は、URL じゃなくて、実ディレクトリベースで解釈されるので、Alias を使うと親子関係が切れてしまうってこと。シンボリックリンクなら大丈夫。

例えば、
ServerName  www.example.com
DocumentRoot  /var/www/html
Alias  child  /opt/html/child
とかいう場合、http://www.example.com/child/index.html へアクセスすると、実ファイルは /opt/html/child/index.html になる。このとき RewriteRule はプレフィックスを /opt/html/child として解釈し、/opt/html/child の .htaccess にある RewriteRule を index.html に適用する。

URL ベースでみると親ディレクトリに相当する /var/www/html は実ディレクトリベースでは親じゃない。なので、/var/www/html に置いた .htaccess の RewiteRule は参照されない。

これが、Alias じゃなくて下のようなシンボリックリンク貼ってると動作する。
/var/www/html/child -> /opt/html/child
この場合、http://www.example.com/child/index.html へアクセスすると、実ファイルは /var/www/html/child/index.html として解釈される。RewriteRule はプレフィックスを /var/www/html/child と解釈し、/var/www/html/child の .htaccess にある RewriteRule を index.html に適用する。

さらに、/var/www/html は親ディレクトリなので DocumentRoot に置いた .htaccess の RewriteRule も適用される。このときプレフィクスは /var/www/html で 適用対象は child/index.html だ。

まとめると、親ディレクトリの .htaccess で RewriteRule 使いたかったら Alias は使わずシンボリックリンクを使えってことなんだけど、これって常識?