Apache Rewriteで %{REQUEST_URI} -f がマッチしない時に読む記事

Linux
Linux
スポンサーリンク

Webサイトを運営していると URLで指定されたファイルやディレクトリが無い場合に、特定のファイルを表示したい時があります。これをよく Apache httpd では mod_rewrite を使って、リライトされる条件(RewriteCond)に %{REQUEST_URI} -f や %{REQUEST_URI} -d を指定して実現するのですが、これがまったく条件にマッチしてくれません、、、そこで今回は、%{REQUEST_URI} -f や %{REQUEST_URI} -d がマッチしない時の対処法とその原因をまとめてみました。

対処法

お急ぎかもしれませんので先に対処法です。リライトされる条件(RewriteCond)に %{DOCUMENT_ROOT} を追加してください。

RewriteCond {REQUEST_URI} -f [OR]
RewriteCond {REQUEST_URI} -d
          ↓
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d

なぜ %{REQUEST_URI} だけではマッチしないのか?

なぜ %{REQUEST_URI} だけではマッチしないのか? その原因を簡単に説明いたします。

%{REQUEST_URI} だけの場合

例えば下のようなリライト設定をしていたとします。

RewriteEngine On
RewriteCond %{REQUEST_URI} -f [OR](ファイルが存在する または)
RewriteCond %{REQUEST_URI} -d   (ディレクトリが存在する)
RewriteRule ^(.*)$ - [L]      (上記にマッチすればなにもしない)
RewriteRule ^(.*)$ /index.php [L] (マッチしなければ /index.php にリダイレクト)

そしてドキュメントルートは「/var/www/html/」で、その直下にリダイレクト先の「index.php」と「sample.html」が存在しています。

/var/www/html/index.php
/var/www/html/sample.html

ブラウザで「sample.html」にアクセスすると、%{REQUEST_URI} -f(ファイルが存在する)の条件にマッチして、そのまま「sample.html」が表示されそうなのですが、残念ながらそうはなりません。Apache httpd のログを確認してみると「/sample.html」が、なぜか not-matched(マッチしない)になっています、、

RewriteCond: input='/sample.html' pattern='-f' => not-matched

%{DOCUMENT_ROOT}%{REQUEST_URI} の場合

では、リライトされる条件(RewriteCond)に %{DOCUMENT_ROOT} を追加してみましょう。

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^(.*)$ - [L]
RewriteRule ^(.*)$ /index.php [L]

ブラウザで「sample.html」にアクセスすると、意図した通りそのまま「sample.html」が表示され、Apache httpd のログは次のようになっています。

RewriteCond: input='/var/www/html/sample.html' pattern='-f' => matched

ここまでくればもうお分かりかと思いますが %{REQUEST_URI} だけでマッチしない原因は、mod_rewrite の -f(ファイルが存在する)や -d(ディレクトリが存在する) は、フルパスで判定しているからです。一方 RewriteRule で指定するリダイレクト先は(上の場合は「/index.php」)Apache httpd のドキュメントルートからのパスで指定します。

mod_rewrite のマニュアルにはしっかり例が示されていました。

For example:

RewriteCond /var/www/%{REQUEST_URI} !-f
RewriteRule ^(.+) /other/archive/$1 [R]

mod_rewrite - Apache HTTP Server Version 2.4 より引用

おわりに

Apache httpd は10年以上使っていますが、mod_rewrite はいまだ苦手です、、(^^;)

コメント

タイトルとURLをコピーしました