CakePHPの環境で、webroot配下以外に静的コンテンツを設置したいという案件があり、ちょこっとはまったのでメモ。
内容は、Directoryディレクティブの内容が複数マッチするリクエストの場合に、どれがマッチするかという話です。
マージの順番は以下のようになっています:
<Directory> (正規表現無し) と .htaccess を同時に (.htaccess が許可されていれば、それが <Directory> を上書きします)
<DirectoryMatch> (と <Directory ~>
<Files> と <FilesMatch> を同時に
<Location> と <LocationMatch> を同時に
<Directory> 以外は、それぞれのグループは設定ファイルに現れた順番に処理されます。 <Directory> (上のグループ 1) はディレクトリが短いものから長いものへと処理されます。ですから、 例えば <Directory /var/web/dir1> は <Directory /var/web/dir/subdir> の前に処理されます。複数の <Directory> セクションが 同じディレクトリに 適用される場合は、設定ファイル中の順番に従って処理されます。 Include によって挿入された設定は 挿入しているファイルの Include ディレクティブの位置にあったかのように扱われます。
<VirtualHost> セクション中のセクションは バーチャルホストの定義の外側の対応するセクションの 後に適用されます。これによりバーチャルホストが メインのサーバ設定を上書きできるようなります。
つまり、ディレクティブに複数マッチする処理があった場合は、パスが短いものから順に処理されていくという話なので、最優先されるのは一番長いパスのものらしい。
検証の結果からいうと、パスが一番長いものが最優先(上書き)されるけど事前に通ったディレクティブ処理も効く=同じディレクティブの記載がある場合のみ上書きされという意味でパスが長いものが優先されるという事だった。
【apacheディレクティブ一覧】
http://httpd.apache.org/docs/2.0/ja/mod/core.html#options
ということで、実際に試してみた。
テストケース
今回は、下記のようなリクエストで、[/test/app/View/test1]配下に置かれた静的コンテンツを返したいとする。
http://localhost/test1/sample.html
まずは、失敗作
cakeなので、ルーティングの為のリライトを標準通りに書いた下記のhttpd.confに、Aliasで該当パスを追加してみたところ、リライトが効いていて404が返る。
あれ、パスが長いものが適用されるんじゃなかったのか。。?
httpd.conf
<Directory /test/app/>
RewriteEngine On
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</Directory>
<Directory /test/app/webroot/>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
RewriteCond %{THE_REQUEST} "^(.+?) (.*?)/app/webroot/(.*?) (.+?)$"
RewriteRule ^(.*?)$ %2/%3 [R=302,L]
</Directory>
Alias /test1 /test/app/View/test1
<Directory /test/app/View/test1>
AllowOverride none
Options -Indexes FollowSymLinks
</Directory>
これが正解
RewriteEngineをオーバーライドしないと上の処理が効くので、cake用のルーティングが行われて404が返るという事だったらしい。
httpd.conf
<Directory /test/app/>
RewriteEngine On
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</Directory>
<Directory /test/app/webroot/>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
RewriteCond %{THE_REQUEST} "^(.+?) (.*?)/app/webroot/(.*?) (.+?)$"
RewriteRule ^(.*?)$ %2/%3 [R=302,L]
</Directory>
Alias /test1 /test/app/View/test1
<Directory /test/app/View/test1>
RewriteEngine On
RewriteRule ^(.*)$ $1
AllowOverride none
Options -Indexes FollowSymLinks
</Directory>