mod_rewriteのRewriteBaseを完全に誤解していたのでメモ。
参考:
嵌った時の条件
→いくら頑張っても404になる。
書いたmod_rewrite設定はこんな感じでした。(RewriteRuleの正規表現は適当にごまかしてる偽物です。)
<DocumentRoot "/var/www/html"> RewriteEngine On RewriteBase /dir1 # これが間違い RewriteRule ^/([a-z]+)/([a-z]+) /cgi-bin/index.pl?p1=dir1&p2=$1&p3=$2 [L] </DocumentRoot>
RewriteBaseを「処理するURLのprefixを指定するもの」と思いこんで"/dir1"を指定していたのが間違いでした。
mod_rewriteのRewriteBaseの挙動をおさらいしてみますと、そもそもmod_rewriteって「rewriteした後のURLで再度Apacheに内部的にリクエストする」という特殊処理があり、この再リクエストの際のディレクトリ補正に使われるのがRewriteBaseです。
上記の設定例ですと、mod_rewriteの内部処理の イメージは こんな感じになるんでしょうか(自信ない・・・)
リクエスト : /dir1/foo/bar (1) /dir1/foo/bar -> /var/www/html/dir1/foo/bar (ApacheのDocumentRootによる変換) (2) /var/www/html/dir1/foo/bar -> "/var/www/html" + "/dir1/foo/bar" →mod_rewriteによるDocumentRoot位置での分割。 (3) "/dir1/foo/bar" -> (RewriteRule) -> "/cgi-bin/index.pl?p1=dir1&p2=dir1&p3=foo [L] →"/dir1"のせいでこの時点で既に意図した方向からズレてる。 (4) RewriteBase + (3) -> "/dir1/cgi-bin/index.pl?p1=dir1&p2=dir1&p3=foo" →内部的な再リクエストのためにRewriteBaseを使って再構築 (5) "/dir1/cgi-bin/index.pl?p1=dir1&p2=dir1&p3=foo" -> /var/www/html/dir1/cgi-bin/index.pl?p1=dir1&p2=dir1&p3=foo → 404 Not Found.
という訳で、いくら頑張っても404 Not Foundになってしまった次第です。
正しいRewriteBaseの設定は、この場合次の2パターンになります。
RewriteBase / # DocumentRootからの相対パス RewriteBase /var/www/html # ファイルシステム上の物理パス
これにより、(4)の時に実際の /cgi-bin/index.pl を指すDocumentRoot相対パス or 物理パスが取得され、(5)で正常にリクエストが渡ります。
RewriteRuleも "/dir1" をちゃんと入れてあげます。
RewriteRule ^/dir1/([a-z]+)/([a-z]+) /cgi-bin/index.pl?p1=dir1&p2=$1&p3=$2 [L]
Alias設定だったときはきちんと物理パスを指定した方が良い?らしい?です?(すみません、これまだ未実験です。)
というわけで、RewriteBaseは「mod_rewriteが書き換え後に再度内部的にリクエストする際のURLパスのprefix」と考えれば大きな勘違いは無くなると思います。
今回の様なパターンで、"dir1, dir2, ..."とかバリエーションが大きい場合は、素直にWebアプリのフロントディスパッチャとかで集中処理した方が、RewriteRuleが簡単に済むと思います。(少なくともsymfonyやCakePHPとかはそうした形の.htaccessになっていたような・・・)