[APACHE DOCUMENTATION]

Apache HTTP Server Version 1.3


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 は以下の二つのフックを使います: HTTP リクエストが読まれた後でかつすべての認証が開始される前に使われる URL-to-filename 変換フック、そして、認証フェーズの後で ディレクトリごとの設定ファイル (.htaccess) が読まれた後、まだ content ハンドラが有効になる前に起動される Fixup フックです。

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

  1. mod_rewrite は URL を URL へ、URL をファイル名へ、 さらにファイル名をファイル名へと書き換えますが、API では現在のところ URL-to-filename フックのみを提供しています。 Apache 2.0 ではそれまでにはなかった二つのフックが追加され、 処理がより明確になりました。 しかしこの点ではユーザにとっての不利益はなく、 単に覚えておくべき事実としては: 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 操作は非常に高速でかつ効率が良いのに対し、 ディレクトリごとの書き換えは、 この鶏と卵の問題のため遅い上に低効率です。しかしこれは、 mod_rewrite がごく平均的なユーザに提供できる、 (ローカルに制限された) URL 操作のための唯一の方法なのです。

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

ルールセット処理

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

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

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

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

特殊文字のクウォート

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

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

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

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


設定ディレクティブ


RewriteEngine

書式: RewriteEngine on|off
デフォルト: RewriteEngine off
コンテキスト: サーバ設定ファイル、 バーチャルホスト、ディレクトリ、.htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

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

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

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


RewriteOptions

書式: RewriteOptions オプション
デフォルト: RewriteOptions MaxRedirects=10
コンテキスト: サーバ設定ファイル、 バーチャルホスト、ディレクトリ、.htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2。MaxRedirects は Apache 1.3.28 以降で使用可能

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

inherit
これは、現在の設定値を親の設定値から強制的に継承させます。 これにより、仮想サーバ単位のコンテキストにおいて、 メインサーバのマップ、条件、ルールが継承されることになります。 また、ディレクトリ単位のコンテキストでは、親ディレクトリの .htaccess 設定に記述されている条件やルールが継承されることになります。
MaxRedirects=number
ディレクトリ毎の RewriteOptions による内部リダイレクトの 無限ループを防ぐために、mod_rewrite はリダイレクトの 上限に達するとリクエストを中止し、500 Internal Server Error を応答として 返します。一つのリクエストに対して本当に 10 を越えるリダイレクトが必要な 場合は、望みの値まで増加させることができます。

RewriteLog

書式: RewriteLog file-path
デフォルト: なし
コンテキスト: サーバ設定ファイル、 バーチャルホスト
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2
 

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

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

例:

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

RewriteLogLevel

書式: RewriteLogLevel Level
デフォルト: RewriteLogLevel 0
コンテキスト: サーバ設定ファイル、 バーチャルホスト
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2

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

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

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

例:

RewriteLogLevel 3

RewriteLock

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

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


RewriteMap

書式: RewriteMap MapName MapType:MapSource
デフォルト:デフォルトでは使用されない
コンテキスト: サーバ設定ファイル、 バーチャルホスト
オーバーライド: 適用不可
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2 (一部のみ), Apache 1.3

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

MapName はマップの名前です。以下の書式のどちらかにより、 書き換えルールの置換文字列で使われる マッピング関数を指定するのに使われます。

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

以下のような MapTypeMapSource を使った組み合わせを使用できます:

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

RewriteBase

書式: RewriteBase URL-path
デフォルト: デフォルトは物理 ディレクトリのパス
コンテキスト: ディレクトリ, .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 のためのディレクトリ別設定ファイル
#  参考:/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 TestString CondPatter
デフォルト: なし
コンテキスト: サーバ設定ファイル、 バーチャルホスト、ディレクトリ、.htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2 (部分的に), Apache 1.3

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

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

考慮事項:

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

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

備考: CondPatternは、 標準の拡張正規表現にいくつか追加を行ったものです:

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

さらに、RewriteCond ディレクティブへの第三引数として CondPattern に特別な

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

使用例:

リクエストの中の ``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 Pattern Substitution
デフォルト: なし
コンテキスト: サーバ設定ファイル、 バーチャルホスト、ディレクトリ、.htaccess
オーバーライド: FileInfo
ステータス: Extension
モジュール: mod_rewrite.c
互換性: Apache 1.2 (partially), Apache 1.3

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

Pattern は現在の 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 の右側の表現で$Nとして参照することが可能。)

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

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

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

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

(訳注: 第2版の日本語版)

詳説 正規表現 第2版
Jeffrey E. F. Friedl 著
田和 勝 訳
オライリー・ジャパン 2003
ISBN 4-87311-130-7

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

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

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

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

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

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

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

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

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

[フラグ]
をつけることができます。 フラグは以下のものをカンマで区切って指定します:
注意: サーバ単位の設定ファイルの中では、Pattern は完全な 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 という二つの (非標準の) 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 に関する追加情報を見ることができるでしょう。

Apache HTTP Server Version 1.3

Index Home