mod_rewrite モジュール
URL 書き換えエンジン

このモジュールは、要求された URL をリアルタイムで書き換える ための、ルールベースの書き換えエンジンを提供します。

ステータス: Extension
ソースファイル: mod_rewrite.c
モジュール識別子: rewrite_module
互換性: Apache 1.2 以降で使用可能



概要

`` mod_rewrite のすばらしいところは、 Sendmailのような設定性と柔軟性を与えてくれるところだろう。 また、mod_rewrite のよくないところは、 Sendmailのような設定性と柔軟性を与えてくれるところだろう。''
-- Brian Behlendorf
Apache Group
`` 膨大な設定例やドキュメントがあるにもかかわらず、 mod_rewrite は黒魔術である。かなりイケてるっぽい黒魔術だが、 やっぱり所詮は黒魔術である。''
-- Brian Moore
bem@news.cmc.net
URL を操作するためのスイス製のアーミーナイフ、mod_rewrite へようこそ!

このモジュールは、(正規表現パーサに基づく)ルールベースの 書き換えエンジンを使い、要求された URL を適宜書き換えます。 サポートするルールの数、および各ルールを適用する際のルール条件 の数に制限はなく、本当にフレキシブルでかつパワフルな URL 操作 メカニズムを提供します。この URL 操作に先立ち、次のようにいろいろな 評価を行なうことができます。たとえばサーバ変数、環境変数、HTTP ヘッダ、 タイムスタンプ、さらに外部データベースの検索結果までを評価の対象として、 各種のフォーマットを使った粒度の高い URL マッチングを実現できます。

このモジュールは、サーバ単位のコンテキスト (httpd.conf) およびディレクトリ単位のコンテキスト (.htaccess) において (PATH-INFO 部分を含む) フル URL に対する操作を行いますが、さらに結果 としてクエリー文字列部分を生成することもできます。出力された結果を 内部のサブプロセスや外部リクエストのリダイレクション、さらには内部の プロキシ処理ルーチンに渡すこともできます。

ただ、これらすべての機能や柔軟性が、欠点や複雑さの元にもなって います。なので、このモジュール全体を一日程度で覚えようなどとは 思わないほうがいいでしょう。

このモジュールは 1996 年の 4 月に

Ralf S. Engelschall
rse@engelschall.com
www.engelschall.com
らにより考案されてオリジナルが書かれ、
1997 年の 7 月に、The Apache Group に対して独占的に贈呈されました。


目次

内部処理

設定ディレクティブ

その他

内部処理


このモジュールの内部処理はとても複雑ですが、ありがちなミスを避け、 また全機能を活用できるように、平均的ユーザに対しても一度は説明して おく必要があります。

API フェーズ

まずは、Apache が HTTP リクエストを処理する際に、このモジュールが このフェーズで行なうことを理解しておかなければなりません。Apache API では、これらの各フェーズに対するフックが提供されています。 mod_rewrite は以下の 2 つのフックを使います: HTTP リクエストが 読まれた後でかつすべての認証が開始される前に使われる URL-to-filename 変換フック、そして、認証フェーズの後でディレクトリ毎の設定ファイル (.htaccess) が読まれたが、まだ content ハンドラが 有効になる前に起動される fixup フックです。

そしてあるリクエストが入って来て、Apache がこれに対応するサーバ (もしくはバーチャルサーバ) を決定した後書き換えエンジンは、サーバ毎の 設定を元に、URL-to-filename フェーズですべての mod_rewrite ディレクティブの処理を開始します。その後多少のステップを経て最後の データディレクトリが見つかった時、ディレクトリ毎の mod_rewrite 設定ディレクティブが fixup フェーズで起動されます。この各々の タイミングの間に特に明らかな違いはないのですが、それでも mod_rewrite はいずれの時にも各 URL を新しい ULR またはファイル名に書き換えます。 これはこの API がデザインされた時に想定された使い方ではないのですが、 Apache 1.x においてはこれが mod_rewrite が動ける唯一の方法でした。 この点をよりはっきりさせるために、以下の 2 点について覚えておいて ください:

  1. mod_rewrite は URL を URL へ、URL をファイル名へ、さらにファイル 名をファイル名へと書き換えますが、API では現在のところ URL-to-filename フックのみを提供しています。Apache 2.0 ではそれまでには なかった 2 つのフックが追加され、処理がより明確になりました。しかし この点でユーザにとっての不利益はなく、単に覚えておくべき事実として: Apache は URL-to-filename フックにおいて API が意図する以上のことを 行ないます。
  2. mod_rewrite では、信じられないことに、URL がファイル名に翻訳 されてからずっと後に辿り着くところにある、ディレクトリ毎の コンテキストすなわち.htaccessファイルの中で URL 操作を行えるようになっていす。.htaccessファイルは ファイルシステム中にあるためにこのようになっているのですが、 処理の流れはすでにこの段階まで到達しているのです。つまりこの時点で API フェーズに従えば、どの URL を操作するにもすでに遅きに失して いるのです。この鶏と卵問題を打開するため、mod_rewrite ではちょっと したトリックを使っています:ディレクトリ毎のコンテキストで URL / ファイル名 の操作を行なう際、mod_rewrite はまずファイル名を対応する URL に戻し (これは通常不可能ですが、これを可能にするトリック についてはRewriteBaseを見てください) 、その新しい URL で内部的に新しいサブリクエストを生成しているのです。これで API フェーズ処理が再度起動されます。

    このように、mod_rewrite は複雑なステップをユーザに対して全般に 透過的にしようとがんばっていますが、とりあえず以下のことは覚えて おいておくべきでしょう:サーバ毎のコンテキストにおける URL 操作は 実際高速でかつ有用であるのに対し、ディレクトリ毎の書き換えは、この 鶏と卵の問題のため遅い上に役に立ちません。しかしこれは、ごく平均的 なユーザにとって、(ローカルに制限された) URL 操作のための唯一の方法 なのです。

これら2つの点を忘れないでください!

ルールセット処理

ここで、これら2つの API フェーズで mod_rewrite が起動されると、 mod_rewrite はまず自分自身の設定用構造体(これらはサーバ毎の コンテキストに伴う起動時か、または Apache カーネルがディレクトリ 毎のコンテキストに従ってディレクトリ間を探索する途中のいずれかに 生成される)より構成されたルールセットを読み込みます。そして その中に入っているルールセット(条件を伴う1つ以上のルールの集まり) と共に URL 書き換えエンジンが開始されます。URL 書き換えエンジン 自体は、双方の設定内容と全く同じように動作します。最終結果の処理が 異なるだけです。

ルールセット中のルールの書き順は重要です。これは、書き換えエンジン はそれらを特別な(かつ、あまり分かりやすいとは言えない)順序で処理 するからです。ルールは以下のように処理されます:書き換えエンジンは ルール(RewriteRuleディレクティブ)を1つずつなめながら ルールセット中をループしますが、ある特別なルールがマッチしたら、それ に対応する条件(RewriteCondディレクティブ)がある間その 中をループします。歴史的な理由によりまず条件が与えられ、その後に制御 フローを書くところがちょっとくどいところです。詳細は Figure 1 をご覧 下さい。

[表示するにはグラフィック機能が必要です]
Figure 1: 書き換えルールセットにおける制御フロー

もうお分かりのように、まず URL を各ルールのパターン に対してマッチングします。マッチしない場合、mod_rewrite はすぐに このルールの処理を中止して次のルールを見に行きます。パターン にマッチすると、mod_rewrite はそれに対応する条件を探します。もし 何もなければ、単に URL を置換対象文字列から作られた新しい 値に置換し、そのルールのループを続けます。何らかの条件があれば、 内部ループを開始し、それらの条件が列挙されている順に処理を繰り返し ます。 その条件に合わなかった場合:現在の URL に対してパターンのマッチング を行ないません。その代わり、まず変数を展開し、後方参照を行い、 検索テーブルをマッピングするなどしてテスト文字列 を生成し、それに対して条件パターンとのマッチングを行ない ます。パターンにマッチしない場合、条件の組合せ全体とそれに対応する ルールは成立しないことになります。パターンにマッチした場合、次の 条件が評価され、それが条件のある限り繰り返されます。もしすべての 条件にマッチすれば、URL は置換対象文字列に置換され、 処理が継続されます。

特殊文字のクウォート

Apache 1.3.20 に関しては、テスト文字列置換対象 文字列の中の特殊文字は、その直前にバックスラッシュ ('\') を置くことで エスケープ(すなわち、それらの持つ特殊な意味を打ち消して、通常の文字 として扱うこと)できます。たとえば、置換対象文字列の中でも '\$' という文字列を使って本来のドル記号を入れることが できるわけです。これにより、mod_rewrite がそれを後方参照として扱おうと するのを防いでいます。

正規表現の 後方参照を使う

ここでひとつ覚えておいて欲しいことがあります:パターン の中や条件パターンのうちのどこかで括弧を使えば、文字列 $N%N で使える後方参照が内部的に生成 されます(後述)。これらは置換対象 文字列やテスト文字列 を生成するのに使えます。Figure 2 では、この後方参照が転送されて展開 される場所について解説します。
[表示するにはグラフィック機能が必要です]
Figure 2: ルールを通した後方参照の流れ

これまでは mod_rewrite の内部処理に関する短期集中コースでした。 ここからは使用可能なディレクティブに関することがかかれています。 これを読めば役立つ知識になってゆくはずです。


設定ディレクティブ


RewriteEngine

書式: RewriteEngine on|off
デフォルト: RewriteEngine off
コンテキスト: server config, virtual host, directory, .htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

RewriteEngineディレクティブを使うと、実行時の 書き換えエンジンを有効にしたり無効にしたりできます。これが offに設定されていると、このモジュールは実行時の 処理を一切行ないません。またSCRIPT_URx環境変数の 更新さえもしなくなります。

RewriteRuleを全部コメントアウトしたりしないで、 このディレクティブを使ってくださいね。

デフォルトでは、rewrite の設定は継承されないので注意してください。 つまり、この機能を使いたいと思うバーチャルホスト毎に RewriteEngine onディレクティブを書かなければいけない ということです。


RewriteOptions

書式: RewriteOptions オプション
デフォルト: なし
コンテキスト: server config, virtual host, directory, .htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

RewriteOptionsディレクティブは、現在のサーバ単位 もしくはディレクトリ単位の設定で使用する、特別なオプションをセット します。オプション文字列は以下のいずれかです:


RewriteLog

書式: RewriteLog file-path
デフォルト: なし
コンテキスト: server config, virtual host
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

RewriteLogディレクティブは、すべての書き換え動作 に関してサーバがログを書き込むためのファイルの名前をセットします。 この名前がスラッシュ ('/') で始まらない場合は Server Rootから相対であると見なされます。このディレクティブ はサーバ単位の設定の中で一度だけ記述されるべきものです。

注意: 書き換え動作のロギングを抑制する ためにファイル名/dev/nullにするのは お勧めできません。これは、書き換えエンジンは実際にはログ ファイルへの出力を行わないのに、未だ内部的にはログファイル への出力を生成しているからです。 これはサーバのパフォーマンスを低下させるだけで、 管理者にとってよいことはありません。ロギングを 抑止する場合はRewriteLogディレクティブを コメントアウトするか、RewriteLogLevel 0を 使うようにしてください!
セキュリティ: ログファイルを格納する ディレクトリが、サーバを起動するユーザ以外にも書き込み可能である 場合に、なぜセキュリティが脅かされるかについての詳しい説明は、 Apache Security Tipsドキュメントをご覧ください。

例:

RewriteLog "/usr/local/var/apache/logs/rewrite.log"

RewriteLogLevel

書式: RewriteLogLevel Level
デフォルト: RewriteLogLevel 0
コンテキスト: server config, virtual host
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

RewriteLogLevelディレクティブでは、書き換え動作時の ログファイルの冗長レベルを指定します。デフォルトのレベルは 0 で、 これは一切ログを書かないことを意味します。一方 9 もしくはそれ以上を 指定すると、ほとんどすべての動作についてログが書かれます。

書き換え動作のログを取らないようにするには、単にLevel を 0 にします。これで書き換え動作に関するすべてのログが無効となります。

注意:Levelに大きな値を指定 すると、Apache サーバの動作速度が劇的に低下します!書き換え時 のログファイルでLevelに 2 以上の値を指定するのは デバッグ時のみにしておいてください!

Example:

RewriteLogLevel 3

RewriteLock

書式: RewriteLock file-path
デフォルト: なし
コンテキスト: server config
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.3

このディレクティブは、mod_rewrite がRewriteMap プログラムと通信するのに必要な、同期用ロックファイルの名前を セットします。RewriteMap プログラムを使いたい場合には、このロック ファイルに(NFS マウントされたデバイスではなく)ローカルパスをセット します。それ以外のタイプの書き換えマップを使う場合には、セットする必要 はありません。


RewriteMap

書式: RewriteMap MapName MapType:MapSource
デフォルト:デフォルトでは使用されない
コンテキスト: server config, virtual host
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2 (partially), Apache 1.3

RewriteMapディレクティブでは、マッピング関数 を使ってルール置換文字列の内部で使える書き換えマップ を定義します。これにより、キーを検索する際に、フィールドを挿入 したり置換したりできます。検索対象には各種のタイプが使えます。

MapNameはマップの 名前です。以下の書き方のいずれかを通して、書き換えルールの置換文字列 におけるマッピング関数を特定するのに使われます。

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }
このような書式が現れると、MapNameマップが評価されて キーLookupKeyが検索されます。キーが見つかれば、置換される 代わりにSubstValueによりマップ関数が呼ばれます。キーが 見つからない場合、DefaultValueがあればそれで置換され、 DefaultValue指定されていなければ空文字列に置換されます。

以下はMapTypeMapSourceを使った組合せです:

RewriteMap ディレクティブは何度でも書くことが できます。各々のマッピング関数について 1 つの RewriteMap を使い、その書き換え用マップファイルを宣言します。ディレクトリ毎の コンテキスト内部でマップを宣言することはできませんが、 ディレクトリ毎のコンテキストでこのマップを使うことは もちろん可能です。
注意:プレーンテキストと DBM フォーマット のファイルに関しては、マップファイルの mtime が変更 されるかまたはサーバが再起動されるまで、検索されたキーはメモリ内に キャッシュされます。それにもかかわらず、毎回の リクエストで使われるマップ関数をルール内に書くことができます。 外部検索は一度しか行なわれないので、これでも大丈夫なのです。

RewriteBase

書式: RewriteBase URL-path
デフォルト: デフォルトは物理 ディレクトリのパス
コンテキスト: directory, .htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

RewriteBase ディレクティブは、ディレクトリ毎の 書き換えにおいてベースとなる URL を明示的に指定するものです。以下 で示すように、RewriteRuleはディレクトリ毎の設定ファイル (.htaccess)で使えます。そこでは、これはローカルに振舞い ます。すなわち、この処理段階ではローカルディレクトリの接頭辞 が取り除かれ、その残りの部分に対してのみ書き換えルールが適用されます。 そして書き換え後、取り除かれた部分が再度自動的にパスに付加されます。

新しい URL に対する置換が発生すると、このモジュールは当該 URL をサーバ処理に再投入しなければなりません。これを行なうには、対応する URL のプリフィックスもしくは URL のベースが何なのかを知る必要が あります。デフォルトではこのプリフィックスはファイルパスそのものに 対応しています。しかしながら、ほとんどの Web サイトでは URL は物理的なファイル名のパスを直接指している *わけではない* ので、 一般的にこの仮定は間違っていることになります。そのため、 RewriteBaseディレクティブを使って正しい URL プリフィックス を指定してやらなければならないのです。

注意:もしあなたの Web サーバの URL が 物理的なファイルパスを直接指しているのでなければ、 RewriteRuleディレクティブを使おうとしているところ すべてについて、各.htaccessファイルで RewriteBaseディレクティブを使わなければなりません。

例:

以下は、ディレクトリ毎の設定ファイルだと思ってください:
#
#  /abc/def/.htaccess -- ディレクトリ /abc/def のための dir 別設定ファイル
#  参考:/abc/def は パス /xyz の物理パス名である。すなわちサーバには
#       'Alias /xyz /abc/def' といったディレクティブの設定がある。
#

RewriteEngine On

#  物理的なパスのプリフィックスである /abc/def でなく、/xyz を通して
#  アクセスしていることをサーバに知らせる。
RewriteBase   /xyz

#  これが書き換えルール
RewriteRule   ^oldstuff\.html$  newstuff.html

上記の例では、/xyz/oldstuff.html へのリクエストで 物理ファイル /abc/def/newstuff.html への正しい 書き換え操作が行なわれます。

Apache ハッカーのための注釈:
以下のリストで示しているのは、内部処理ステップに関する 詳細情報です:
リクエスト:
  /xyz/oldstuff.html

内部処理:
  /xyz/oldstuff.html     -> /abc/def/oldstuff.html  (per-server Alias)
  /abc/def/oldstuff.html -> /abc/def/newstuff.html  (per-dir    RewriteRule)
  /abc/def/newstuff.html -> /xyz/newstuff.html      (per-dir    RewriteBase)
  /xyz/newstuff.html     -> /abc/def/newstuff.html  (per-server Alias)

処理結果:
  /abc/def/newstuff.html

これは非常に複雑に見えるものの、Apache の 内部処理に関する正しい動きです。なぜなら、ディレクトリ単位の 書き換え操作は処理の中において来るのが遅すぎるのです。 そのためこれが発生すると、(書き換えが行なわれた)リクエスト は Apache カーネルの中に再投入されなければなりません! しかし:これは深刻なオーバーヘッドを伴うように見えるものの、 実際には大した事はありません。それは、この再投入は完全に Apache サーバの内部で起こる事であり、Apache の内部における その他の多くの動作中にも同様のことが起こっているからです。 なので、その設計と実装は正しいのだと確信して構わないのです。

RewriteCond

書式: RewriteCond テスト文字列 条件パターン
デフォルト: なし
コンテキスト: server config, virtual host, directory, .htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2 (部分的に), Apache 1.3

RewriteCondディレクティブはルール条件を定義します。 RewriteRuleディレクティブの前に 1 つ以上の RewriteCondディレクティブを置くことができます。それ以降の 書き換えルールは、そのパターンが現在の URI の状態とマッチし、 かつこれらの追加条件が適用される場合にのみ使われます。

テスト文字列は文字列であり、プレーンテキストに加え、 以下の拡張構造を持つことができます:

考慮事項:

  1. SCRIPT_FILENAME および REQUEST_FILENAME には同じ名前、 すなわち、Apache サーバの request_rec 内部構造体の中の filename フィールドの値が入って います。前者は単によく知られている CGI 変数名であるのに対し、 後者は(request_rec フィールドのuri の値が入っている)REQUEST_URI に一致するものです。
  2. 特別な書式: %{ENV:変数} ここで変数は任意の環境変数 です。これは Apache の内部構造体もしくは(そこに存在しなければ) Apache サーバプロセスが発行する getenv() を通して 検索されます。
  3. 特別な書式: %{HTTP:ヘッダ} ここで ヘッダ は任意の HTTP MIME ヘッダ名です。これは HTTP リクエストから検索されます。 例:%{HTTP:Proxy-Connection} は HTTP ヘッダの ``Proxy-Connection:'' の値です。
  4. 特別な書式: %{LA-U:変数} は前方参照であり、内部の(URL ベースの) サブリクエストを実行して変数の最終値を決定します。 実際には API フェーズの後のほうでセットされるために、現時点では アクセスできないような変数を使って書き換えを行ないたい場合に 使用します。たとえば、サーバ単位のコンテキスト(httpd.conf file)から来る REMOTE_USER 変数にしたがって 書き換えを行ないたい場合には、 %{LA-U:REMOTE_USER} を使用しなければなりません。なぜなら、この変数は mod_rewrite が 動作する URL 変換フェーズのにある認証フェーズでセット されるものだからです。一方、mod_rewrite は API の Fixup フェーズ を通してディレクトリ単位のコンテキスト(.htaccess file)を実装しており、かつ認証フェーズはこのフェーズの に行なわれるため、そこでは単に %{REMOTE_USER} とする ことができるのです。
  5. 特別な書式: %{LA-F:変数} これは内部の(ファイル名ベースの)サブ リクエストを実行して変数の最終値を決定します。ほとんどの 場合これは前述の LA-U と同じです。

条件パターン は、現在のテスト文字列の実体に 対して適用される正規表現です。テスト文字列は評価された後に 条件パターンに対してマッチングが行なわれます。

備考: 条件パターンは、標準の 拡張正規表現にいくつか追加を行なったものです:

  1. '!' 文字(エクスクラメーションマーク)をパターン 文字列の前につけることで、マッチしないパターン を指定できます。
  2. 条件パターンのちょっとした変種もあります。実際の正規表現 文字列の代わりに以下のように使うことができます:
    • '<条件パターン' (字句の並び的に、 より小さい)
      条件パターンを単なる文字列として扱い、字句の並びと してテスト文字列と比較します。テスト文字列が 字句の並びとして条件パターンより小さい場合に真に なります。
    • '>条件パターン' (字句の並び的に、 より大きい)
      条件パターンを単なる文字列として扱い、字句の並びと してテスト文字列と比較します。テスト文字列が 字句の並びとして条件パターンより大きい場合に真に なります。
    • '=条件パターン' (字句の並び的に等しい)
      条件パターンを単なる文字列として扱い、字句の並びと してテスト文字列と比較します。テスト文字列が 字句の並びとして条件パターンと等しい場合、すなわち、 2 つの文字列が(1 文字ずつ比較して)正確に等しい場合に真に なります。もし条件パターンが単なる"" (2 つの引用符)であれば、テスト文字列は空文字列と 比較されます。
    • '-d' (directory)
      テスト文字列をパス名として扱い、それが存在して、かつ ディレクトリであれば真。
    • '-f' (通常 file)
      テスト文字列をパス名として扱い、それが存在して、かつ 通常ファイルであれば真。
    • '-s' (size がある通常 ファイル)
      テスト文字列をパス名として扱い、それが存在して、かつ サイズが 0 より大きい通常ファイルであれば真。
    • '-l' (シンボリック link)
      テスト文字列をパス名として扱い、それが存在して、かつ シンボリックリンクであれば真。
    • '-F' (サブリクエストを通した既存ファイル)
      テスト文字列が有効なファイルであること、そしてこの サーバにおいて、現時点で設定されているすべてのアクセス制御を 通して、そのパス名でアクセスできるかどうかをチェックします。 これは内部のサブリクエストを使ってチェックを行なうので、注意 して使わないとサーバのパフォーマンスを低下させることに なりかねません!
    • '-U' (サブリクエストを通した既存 URL)
      テスト文字列が有効な URL であること、そしてこの サーバにおいて、現時点で設定されているすべてのアクセス制御を 通して、そのパス名でアクセスできるかどうかをチェックします。 これは内部のサブリクエストを使ってチェックを行なうので、注意 して使わないとサーバのパフォーマンスを低下させることに なりかねません!
    注意:以上すべてのテストについて、 エクスクラメーションマーク ('!') を前に置くことにより それらの意味を否定することができます。

さらに、RewriteCondディレクティブへの第3引数として 条件パターンに特別な

[フラグ]
を追加することができます:フラグは以下のものをカンマ 区切りで並べたものです:

使用例:

リクエストの中の ``User-Agent:'' ヘッダにしたがって ホームページサイトの書き換えを行なうには、以下のようにします:
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]
解釈:ブラウザとして(自分自身で 'Mozilla' と名乗っている)ネット スケープナビゲータを使う場合、フレームなどを含む max の ホームページを見ることになります。(端末ベースの)Lynxブラウザを 使う場合は、画像やテーブルなどを含まない min のホーム ページが表示されます。それ以外のブラウザの場合は標準(std)のページ が表示されます。

RewriteRule

書式: RewriteRule パターン 置換対象
デフォルト: なし
コンテキスト: server config, virtual host, directory, .htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2 (partially), Apache 1.3

RewriteRuleディレクティブは、実際の書き換えを 担当してくれる馬車馬です。このディレクティブは複数回書くことが できます。各ディレクティブは1つの書き換えルールを定義します。 これらルールを定義する順序は重要です。なぜなら、 実行時にルールを適用する際、この順序で行なわれるからです。

パターンは、 現在の URL に適用される(Apache 1.1.x では System V8、Apache 1.2.x 以降では POSIX の)正規表現 です。ここで「現在の」と言っているのは、ルールが適用される際の URL の値のことです。これはリクエストされたオリジナルの URL で あるとは限りません。なぜならすでに数多くのルールがマッチして、 それを書き換えた後かもしれないからです。

正規表現の文法に関するヒント:

テキスト:
  .           任意の一文字
  [chars]     文字クラス:いずれかの文字
  [^chars]    文字クラス:これら以外の文字
  text1|text2 選択肢:text1 または text2

文字数指定:
  ?           直前の文字の 0 回または 1 回の繰り返し
  *           直前の文字の 0 回以上の繰り返し
  +           直前の文字の 1 回以上の繰り返し

グルーピング:
  (text)      テキストのグルーピング
              (選択肢の境界を明示する、もしくは後方参照を作成するために使う。
               N番目のグループは、RewriteRule の RHS で$Nとして参照される。)

文字位置の指定:
  ^           行頭
  $           行末

エスケープ:
  \char       特殊文字をエスケープ(効果を打ち消す)する
              (たとえば ".[]()" など)

正規表現に関する情報は、ローカルの regex(3) man ページか または Apache 1.3 の配布物に含まれるsrc/regex/regex.3 を参照してください。もし正規表現やその変種(POSIX regex, Perl regex, など)に興味があれば、以下の専門書をご覧下さい:

Mastering Regular Expressions
Jeffrey E.F. Friedl
Nutshell Handbook Series
O'Reilly & Associates, Inc. 1997
ISBN 1-56592-257-3

さらに、mod_rewrite ではパターンの前に NOT 文字('!') が使えます。これで後続のパターンを否定することができます。たとえて 言うならば、``もし現在の URL がこのパターンにマッチ しなければpattern'' ということです。これは、反対の パターンを表す方が簡単だったり、最後のデフォルトルールとするなど、 例外的なケースを表現するのにも使えます。

注意:NOT 文字を使ってパターンを否定 する場合は、パターン中にグループ化されたワイルドカード部分を 入れることはできません。これは、パターンがマッチ *しない* 時、 そのグループの中身がなくなってしまうからです。その結果、もし 否定されたパターンが使われると、置き換え文字列の中で$N が使えなくなってしまいます!

書き換えルールの置換対象 は、パターンがマッチした場合にオリジナルの URL から置き 換えられる文字列です。プレーンテキストの他に以下のものが使えます。

  1. RewriteRule パターンへの後方参照 $N
  2. 最後にマッチした RewriteCond パターンへの後方参照 %N
  3. ルール条件のテスト文字列としてのサーバ変数 (%{変数名})
  4. マッピング関数 の呼び出し (${mapname:key|default})
後方参照は $N(N=0..9) 識別子で表します。これは、マッチしたパターンのグループの 中で、N番目のものの内容に置き換えられます。サーバ 変数はRewriteCondディレクティブのテスト文字列 と同じです。マッピング関数はRewriteMapディレクティブ から来たもので、ここで説明しています。これら 3 タイプの変数は、 上記の順序で展開されます。

前述のように、すべての書き換えルールは置換対象に 対して(設定ファイルに定義してある順に)適用されます。URL は 置換対象によって完全に置き換えられ、 書き換え処理はLフラグ -- 後述 -- によって明示的に終端されていない限り、ルールがなくなるまで 続けられます。

'-' と呼ばれる特殊な置き換え文字列があります。 これは、置換禁止!の意味です。変でしょ?いいえ、 これは URL のマッチングだけを行い、置換を行なわ ないという機能を提供してくれるものです。すなわちC (chain) フラグといっしょに使うことによって、 置換が行なわれる前に複数のパターンを適用することができます。

もうひとつ注意事項:クエリー文字列部分を付加した置換文字列 で URL を生成することもできます。単に、置換文字列の中にクエス チョンマークを入れるだけで、それ以降は QUERY_STRING に入れるべき ことを示します。既存のクエリー文字列を消去したい場合は、置換文字列 をクエスチョンマークだけで終わらせるようにします。

注意: 特殊機能について述べます: 置換フィールドの前に http://thishost[:thisport] を置くと、mod_rewriteは自動的にこれを除去 します。この暗黙の外部リダイレクト URL における自動変換機能は、 ホスト名部分を生成するマッピング関数と同時に使う場合に便利で かつ重要なものです。これを理解するには、以下のサンプルの章の 最初の例を見てください。
備考:この機能の影響で、自分自身のサーバ への無条件の外部リダイレクションは、http://thishost プリフィックスがついていると動作しません。このような自己 リダイレクトを行なうには、Rフラグを使う 必要があります(後述)。

RewriteRuleディレクティブの第三引数として、 置換対象に対して上記以外にも以下のような

[フラグ]
をつけることができます。フラグは以下のものをカンマで 区切って指定します:
注意:サーバ単位の設定ファイルの中では、 パターンは完全な URL に適用されることを忘れないで ください。しかしながら、ディレクトリ単位の設定ファイル の中では、パターンマッチングのためにディレクトリ単位の接頭辞 (これは特定のディレクトリでは常に同じものです!)が自動的に 取り除かれ、置換が終わった後に自動的に付加 されます。この機構は、さまざまな種類の書き換え操作に おいて欠くことのできないものです。なぜなら、この接頭辞のスキップ が行なわれないと、常に存在するとは限らない親ディレクトリとの マッチングを行なわなければならなくなるからです。

ひとつ例外があります:置換文字列が ``http://'' で始まっている場合、ディレクトリ接頭辞は付加されず 、外部リダイレクトまたは(Pフラグが 使われていれば!)プロキシ処理が強制的に行なわれます。

注意:ディレクトリ単位の設定ファイル における書き換えエンジンを有効にする場合、これらのファイルに ``RewriteEngine On'' をセットし、かつ ``Options FollowSymLinks'' を有効に しなければなりません。あなたのところの管理者がユーザの ディレクトリの FollowSymLinks をオーバーライド を禁止していた場合、書き換えエンジンを使うことはできません。 この制限が必要なのは、セキュリティ関連の理由によります。

以下に有効な置換の組合せと、それらの意味を示します:

リクエスト ``GET /somepath/pathinfo'' が行なわれた場合の、
サーバ単位の設定(httpd.conf)の内部:

与えられたルール                                      置換結果
----------------------------------------------  ----------------------------------
^/somepath(.*) otherpath$1                      無効なのでサポートしない

^/somepath(.*) otherpath$1  [R]                 無効なのでサポートしない

^/somepath(.*) otherpath$1  [P]                 無効なのでサポートしない
----------------------------------------------  ----------------------------------
^/somepath(.*) /otherpath$1                     /otherpath/pathinfo

^/somepath(.*) /otherpath$1 [R]                 外部リダイレクション経由で
                                                http://thishost/otherpath/pathinfo

^/somepath(.*) /otherpath$1 [P]                 無意味なのでサポートしない
----------------------------------------------  ----------------------------------
^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^/somepath(.*) http://thishost/otherpath$1 [R]  外部リダイレクション経由で
                                                http://thishost/otherpath/pathinfo

^/somepath(.*) http://thishost/otherpath$1 [P]  無意味なのでサポートしない
----------------------------------------------  ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1     外部リダイレクション経由で
                                                http://otherhost/otherpath/pathinfo

^/somepath(.*) http://otherhost/otherpath$1 [R] 外部リダイレクション経由で
                                                http://otherhost/otherpath/pathinfo
                                                ([R] フラグは冗長)

^/somepath(.*) http://otherhost/otherpath$1 [P] 内部プロキシ経由で
                                                http://otherhost/otherpath/pathinfo

リクエスト ``GET /somepath/localpath/pathinfo'' が行なわれた場合の、
/somepathに関するディレクトリ単位の設定の内部:
たとえば/physical/path/to/somepath ディレクトリにあって、
RewriteBase /somepath の記述がある .htaccess ファイル):

与えられたルール                                      置換結果
----------------------------------------------  ----------------------------------
^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo

^localpath(.*) otherpath$1  [R]                 外部リダイレクション経由で
                                                http://thishost/somepath/otherpath/pathinfo

^localpath(.*) otherpath$1  [P]                 無意味なのでサポートしない
----------------------------------------------  ----------------------------------
^localpath(.*) /otherpath$1                     /otherpath/pathinfo

^localpath(.*) /otherpath$1 [R]                 外部リダイレクション経由で
                                                http://thishost/otherpath/pathinfo

^localpath(.*) /otherpath$1 [P]                 無意味なのでサポートしない
----------------------------------------------  ----------------------------------
^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^localpath(.*) http://thishost/otherpath$1 [R]  外部リダイレクション経由で
                                                http://thishost/otherpath/pathinfo

^localpath(.*) http://thishost/otherpath$1 [P]  無意味なのでサポートしない
----------------------------------------------  ----------------------------------
^localpath(.*) http://otherhost/otherpath$1     外部リダイレクション経由で
                                                http://otherhost/otherpath/pathinfo

^localpath(.*) http://otherhost/otherpath$1 [R] 外部リダイレクション経由で
                                                http://otherhost/otherpath/pathinfo
                                                ([R] フラグは冗長)

^localpath(.*) http://otherhost/otherpath$1 [P] 内部プロキシ経由で
                                                http://otherhost/otherpath/pathinfo

例:

ここでは、
/ Language /~ Realname /.../ File
という書式の URL を
/u/ Username /.../ File . Language
に書き換えたいものとします。

前述のマップファイルを /path/to/file/map.txt という名前でセーブしておきます。その後、Apache サーバ設定 ファイルに以下の行を追加するだけです:

RewriteLog   /path/to/file/rewrite.log
RewriteMap   real-to-user               txt:/path/to/file/map.txt
RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1

その他の情報


環境変数

このモジュールは、SCRIPT_URLSCRIPT_URI という2つの(非標準の)CGI/SSI 環境変数を設定します。これらの中には 現在のリソースへの論理的な Web ビューが入っています。一方、 標準の CGI/SSI 変数であるSCRIPT_NAMESCRIPT_FILENAMEには、物理的なシステムビューが 入っています。

注意:これらの変数の中には、最初にリクエストを受けた時点 すなわち、書き換えが行なわれる前の URI/URL が保持 されています。URL 書き換え処理は、論理的な URL を物理的なパス名に 書き換えるために使われることが多いため、この点は重要です。

例:

SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
SCRIPT_FILENAME=/u/rse/.www/index.html
SCRIPT_URL=/u/rse/
SCRIPT_URI=http://en1.engelschall.com/u/rse/

実践的な解決法

この文書以外にも、URL Rewriting Guide という文書があります。この中には、URL ベースの問題について、実践的な解決法が集められています。 ここで実際に役立つルールセットや mod_rewrite に関する追加情報を 見ることができるでしょう。