home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Apache/mod_rewriteメモ(1):RewriteBaseの誤解 (v2)

技術/Apache/mod_rewriteメモ(1):RewriteBaseの誤解 (v2)

技術 / Apache / mod_rewriteメモ(1):RewriteBaseの誤解 (v2)
id: 167 所有者: msakamoto-sf    作成日: 2009-02-08 20:43:38
カテゴリ: Apache 

mod_rewriteのRewriteBaseを完全に誤解していたのでメモ。

参考:

嵌った時の条件

  1. DocumentRootにmod_rewriteを設定。
  2. "/dir1/$1/$2" という感じのURLを、"/cgi-bin/index.pl?p1=dir1&p2=$1&p3=$2"とかにしたかった。
  3. 「"/dir1"で始まるURLに適用したい」ので、RewriteBaseに "/dir1" と設定(ここが間違い)。

→いくら頑張っても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になっていたような・・・)


プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2009-02-16 23:22:19
md5:ea85f552b11c935d511ed1e2fd6f40ee
sha1:b2c889af20b0b651964247b3e7a27b1c7c8b1070
コメント
コメントを投稿するにはログインして下さい。