.htaccess ファイルで mod_rewrite の設定をする時の注意点


Apache の mod_rewrite の設定は、サーバの設定ファイル(httpd.conf)内で指定する場合と .htaccess ファイル(または <Directory>コンテキスト)で指定する場合で少し違う点がある。

先日 Yahoo 知恵袋で質問に回答した時に、設定ファイルを見ていただけでは気づかず、検証せずに回答して失敗しました。ごめんなさい。

教えてもらった設定が動かないとか、いつもやっている筈の書き方がどうもうまく行かないという場合は、これらの違いにハマっている可能性があります。

書き換え処理が繰り返される

.htaccess ファイルでURLの書き換えを行うと、1回一連の書き換えが終わった後、もう一度書き換え設定を上から順に適用し、書き換えの必要がないかをチェックする。書き換える必要が無くなるか、またはループしすぎてエラーになるまでこれが続く。

これは、[L] フラグを指定しても、外部へのリダイレクト、つまり [R] フラグと一緒に指定していない限り起こる。

Apache ドキュメントのフラグの設定のところにその説明がある。要点としては、.htaccess で指定した場合処理が繰り返されるから、適当に RewriteCond などで条件を入れるように注意してね、という事。

If you are using RewriteRule in either .htaccess files or in <Directory> sections, it is important to have some understanding of how the rules are processed. The simplified form of this is that once the rules have been processed, the rewritten request is handed back to the URL parsing engine to do what it may with it. It is possible that as the rewritten request is handled, the .htaccess file or <Directory> section may be encountered again, and thus the ruleset may be run again from the start. Most commonly this will happen if one of the rules causes a redirect – either internal or external – causing the request process to start over.

It is therefore important, if you are using RewriteRule directives in one of these contexts, that you take explicit steps to avoid rules looping, and not count solely on the [L] flag to terminate execution of a series of rules, as shown below.

拙訳

もし .htaccess ファイルや <Directory> セクションで RewriteRule を使っているのであれば、どのようにルールが処理されるかを理解しておく事は重要です。単純に言うと、一連のルールが1回処理された後、書き換え後のURLはもう一度「URL解析エンジン」に渡され、何か処理するべき事があればその処理を行います。その時、もう一度同じ .htaccess ファイルや <Directory> セクション内の設定が初めから適用されるという事も起こり得ます。これが起こる典型的なケースは、外部でも内部でもリダイレクトの処理を行った時です。

このため、これらのどちらかのセクションで RewriteRule を使用しているのであれば、処理がループされてしまうのを避けるために細かく設定をしておく事が重要で、[L] フラグのみで処理を終了させようとするのでは不足です。

ディレクトリコンテキストでは暗黙のうちに [PT] フラグが付いている

これはつまり、サーバ設定ファイル(httpd.conf)では URL 書き換え先にファイルシステム上のパスを指定できるが、.htaccess ではできないという事。また別の言葉では、.htaccess での書き換え先パス指定は常に URI として解釈されるという事。

サーバ設定ファイルでは、書き換え先パスの先頭に「/」が付いていると、まずその先頭のディレクトリがファイルシステム上にあるかを探す。該当するディレクトリがあればファイルシステム上のファイル指定だと見做してそのファイルにマッピング。もしファイルシステム上に先頭のディレクトリが無ければURL上の「/」、つまり、サーバルートからのパスが指定されたと見做す。しかしサーバルートからの指定に関しても、URI として解釈するのではなくファイルシステム上のドキュメントルート以下のファイルを探す。このため、Alias されているパスなどを指定すると 404 エラーとなる。このような URI への書き換えを行いたい場合は[PT] フラグを付ける。[PT] フラグを付けると、[L] も指定したと見做される。

一方 .htaccess の場合は、常に書き換え先パス指定を URI として解釈する
http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_pt

Note that the PT flag is implied in per-directory contexts such as <Directory> sections or in .htaccess files. The only way to circumvent that is to rewrite to -.

拙訳

PT フラグは <Directory> セクションや .htaccess のようなディレクトリコンテキストでは暗黙のうちに有効になっています。これを避ける唯一の方法は、「-」への書き換え設定です。

相対パスは RewriteBase を起点にする

.htaccess での指定では、RewriteBase でこのファイルを置いているディレクトリを指定する。

書き換え元パスはこの RewriteBase ディレクトリからの相対パスで解釈されるため、^/(.*) など、スラッシュで始まる条件指定は .htaccess では決してマッチしない。

書き換え先パスは、サーバ設定ファイルでは、(当然ながら)相対パス(「/」から始まらないパス)は使えないが、.htaccess では相対パスと「/」から始まるサーバルートからのパスが両方とも使える。(「/」から始まるパスの解釈がサーバ設定ファイル内での指定とは少し違う点は上述の通り。)

相対パスの指定は、常に RewriteBase からの相対パスと見做される。サブディレクトリに .htaccess が適用された場合にもサブディレクトリからの相対パスにはならない事に注意。