【PHP】VirtualHostにリライト設定を書いたときの SCRIPT_NAME の値がおかしい
PHPのサーバ環境変数に、SCRIPT_NAME という値があります。
「現在の実行ファイルのパス」が入り、例えば、以下のようなリライト設定で、
RewriteRuleに引っかかるリクエストでは、「/index.php」が入ります。
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [QSA,L]
しかし設定の記述場所によっては、「/index.php」が入らないケースがあるようです。
リライトの設定場所って...なんか毎回ハマっている気がします。
リライト設定を記述できる場所は2箇所。
- Directoryディレクティブ(=.htaccess)
- VirtualHost内
Directoryディレクティブまたは、.htaccess の場合は、どちらに書いても「/index.php」になります。
(以下は、Directoryディレクティブの場合。)
しかし、VirtualHost内では、なんと「/index.php」とはなりません。
<VirtualHost *:80> ServerName example.com DocumentRoot /var/www/html DirectoryIndex index.php index.html <Directory "/var/www/html"> <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [QSA,L] </IfModule> </Directory> </VirtualHost>
VirtualHost内に書いた場合
httpd.conf の設定
<VirtualHost *:80> ServerName example.com DocumentRoot /var/www/html DirectoryIndex index.php index.html <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /index.php [QSA,L] </IfModule> </VirtualHost>
ファイル構成
ドキュメントルート直下に、index.php がおいてある(/var/www/html/index.php)
リクエストと結果
上記内容で、http://example.com/hoge/hige/ にアクセスします。
すると、SCRIPT_NAME の値は「/hoge/hige/」なります。
これは、REQUEST_URI と同じ値で、「/index.php」を期待しますがそうはならないのです。
何が違うのか?
VirtualHostに書いた場合とDirectoryディレクティブに書いた場合とで動作はどのように違うのでしょうか。リライトログを追ってみました。
■ VirtualHost リライトログ(※メッセージ部分のみ抽出)
[example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] init rewrite engine with requested uri /hoge/hige/ [example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] applying pattern '^(.*)$' to uri '/hoge/hige/' [example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] RewriteCond: input='/hoge/hige/' pattern='!-f' => matched [example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] rewrite '/hoge/hige/' -> '/index.php' [example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] local path result: /index.php [example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] prefixed with document_root to /var/www/html/index.php [example.com/sid#7f1ac4223418][rid#7f1ac4433670/initial] go-ahead with /var/www/html/index.php [OK]
■ Directoryディレクティブ リライトログ(※メッセージ部分のみ抽出)
[example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] add path info postfix: /var/www/html/hoge -> /var/www/html/hoge/hige/ [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] strip per-dir prefix: /var/www/html/hoge/hige/ -> hoge/hige/ [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] applying pattern '^(.*)$' to uri 'hoge/hige/' [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] RewriteCond: input='/var/www/html/hoge' pattern='!-f' => matched [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] rewrite 'hoge/hige/' -> 'index.php' [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] add per-dir prefix: index.php -> /var/www/html/index.php [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] strip document_root prefix: /var/www/html/index.php -> /index.php [example.com/sid#7fa563ae9418][rid#7fa563cf9670/initial] [perdir /var/www/html/] internal redirect with /index.php [INTERNAL REDIRECT] [example.com/sid#7fa563ae9418][rid#7fa563ce44f0/initial/redir#1] [perdir /var/www/html/] strip per-dir prefix: /var/www/html/index.php -> index.php [example.com/sid#7fa563ae9418][rid#7fa563ce44f0/initial/redir#1] [perdir /var/www/html/] applying pattern '^(.*)$' to uri 'index.php' [example.com/sid#7fa563ae9418][rid#7fa563ce44f0/initial/redir#1] [perdir /var/www/html/] RewriteCond: input='/var/www/html/index.php' pattern='!-f' => not-matched [example.com/sid#7fa563ae9418][rid#7fa563ce44f0/initial/redir#1] [perdir /var/www/html/] pass through /var/www/html/index.php
詳しく見ると、Directoryディレクティブ では、内部リダイレクトが発生して、2回リライト設定を通っていることが分かります。 リダイレクト前と後では、リクエストパスが変わります。
1回目 … /hoge/hige/
2回目 … /index.php ★
一方で、VirtualHostに書いた場合は、リクエストは繰り返されることはありません。1回のみです。
1回目 … /hoge/hige/ ★
どうやら、★で記したところの情報が、PHPの$_SERVER['SCRIPT_NAME']に入るようです。(これは上の結果からの推測ですが...)
この値は、Apache上では、REQUEST_FILENAME という変数になるため、SCRIPT_NAMEは、
内部リダイレクトした時も含めた最終リクエスト時の REQUEST_FILENAME が入る
といったところではないでしょうか。
ただ、内部リダイレクトあるなしの挙動の違いだけで、これ以上詳しいことは分かりませんでした。 Directoryディレクトティブで内部リダイレクトなしにできないのかとか 逆に、VirtualHostで内部リダイレクトできないのか等が気になります。
リライト設定はDirectoryディレクティブへ
VirtualHost設定に書いた場合は、罠が多いように思います。
.htaccess と記述を合わせることのできるメリットもありますし、リライト設定はDirectoryディレクティブへ書くのが好ましいと思いました。