<-
Apache > HTTP サーバ > ドキュメンテーション > バージョン 2.5 > Rewrite

RewriteMap の使用

翻訳済み言語:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn 

このドキュメントは mod_rewrite リファレンスドキュメントを補足するものです。 RewriteMap ディレクティブの使用方法を 説明し、さまざまな RewriteMap タイプの例を提供します。

これらの例の多くは、特定のサーバ設定ではそのまま 動作しないことに注意してください。そのため、単にコピー&ペーストするのではなく、 内容を理解することが重要です。

参照

top

はじめに

RewriteMap ディレクティブは、 RewriteRule または RewriteCond ディレクティブの コンテキストで呼び出せる外部関数を定義し、正規表現だけでは実行が 複雑すぎたり特殊すぎたりする書き換えを行います。この検索のソースは、 以下のセクションに記載されているタイプのいずれかで、 RewriteMap リファレンス ドキュメントに列挙されています。

RewriteMap ディレクティブの構文は以下の通りです:

RewriteMap MapName MapType:MapSource

MapName は、 マップに割り当てる任意の名前で、後のディレクティブで使用します。 引数は以下の構文でマップに渡されます:

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }

このような構文が出現すると、マップ MapName が参照され、 キー LookupKey が検索されます。キーが見つかった場合、 マップ関数の構文は SubstValue で置換されます。キーが 見つからなかった場合は、DefaultValue で置換されるか、 DefaultValue が指定されていない場合は空文字列で 置換されます。

例えば、RewriteMap を 以下のように定義できます:

RewriteMap examplemap "txt:/path/to/file/map.txt"

その後、このマップを RewriteRule で以下のように使用できます:

RewriteRule "^/ex/(.*)" "${examplemap:$1}"

マップで何も見つからなかった場合に備えて、デフォルト値を指定 できます:

RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}"

ディレクトリ単位および .htaccess コンテキスト

RewriteMap ディレクティブは <Directory> セクションや .htaccess ファイルでは使用できません。マップはサーバまたは バーチャルホストのコンテキストで宣言する必要があります。作成したマップは、 それらのスコープ内の RewriteRule および RewriteCond ディレクティブで使用できます。それらのスコープでマップを 宣言することはできません。

以下のセクションでは、使用可能なさまざまな MapType を 説明し、それぞれの例を示します。

top

int: 内部関数

MapType に int を使用すると、MapSource は利用可能な 内部 RewriteMap 関数の いずれかになります。モジュール作成者は、 ap_register_rewrite_mapfunc API を使用して追加の内部 関数を登録できます。 デフォルトで提供される関数は以下の通りです:

これらの関数のいずれかを使用するには、int 関数を参照する RewriteMap を作成し、 RewriteRule で使用します:

URI をすべて小文字のバージョンにリダイレクト

RewriteMap lc int:tolower
RewriteRule "(.*)" "${lc:$1}" [R]

ここで提供されている例は説明目的のみであり、推奨ではありません。 URL を大文字小文字を区別しないようにしたい場合は、代わりに mod_speling の使用を検討してください。

top

txt: プレーンテキストマップ

MapType に txt を使用すると、MapSource はプレーンテキストの マッピングファイルへのファイルシステムパスで、1 行に 1 つのスペース区切りの キー/値ペアが含まれます。オプションで、'#' 文字で始まるコメント行を 含めることができます。

有効なテキスト書き換えマップファイルの構文は以下の通りです:

# コメント行
MatchingKey SubstValue
MatchingKey SubstValue # コメント

RewriteMap が呼び出されると、 引数が各行の最初の引数から検索され、見つかった場合は置換値が 返されます。

例えば、マップファイルを使用して製品名を製品 ID に変換し、 覚えやすい URL を実現するには、以下のレシピを使用できます:

製品から ID への設定

RewriteMap product2id "txt:/etc/apache2/productmap.txt"
RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]

ここでは、prods.php スクリプトが id=NOTFOUND という引数を受け取った場合の処理を 理解していると仮定しています (検索マップで製品が見つからなかった場合)。

ファイル /etc/apache2/productmap.txt には 以下が含まれます:

製品から ID へのマップ

##
## productmap.txt - 製品から ID へのマップファイル
##

television 993
stereo 198
fishingrod 043
basketball 418
telephone 328

したがって、http://example.com/product/television が リクエストされると、RewriteRule が適用され、リクエストは内部的に /prods.php?id=993 にマッピングされます。

注: .htaccess ファイル

この例はサーバまたはバーチャルホストのスコープで使用するよう 作成されています。.htaccess ファイルで使用する場合は、 何かにマッチするように書き換えパターンから先頭のスラッシュを 削除する必要があります:
RewriteRule "^product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]

キャッシュされた検索

検索されたキーは、マップファイルの mtime (変更時刻) が 変更されるか、httpd サーバが再起動されるまで httpd にキャッシュ されます。これにより、多くのリクエストで呼び出されるマップの パフォーマンスが向上します。

top

rnd: ランダム化プレーンテキスト

MapType に rnd を使用すると、MapSource はプレーンテキストの マッピングファイルへのファイルシステムパスで、各行にはキーと | で区切られた 1 つ以上の値が含まれます。キーが マッチすると、これらの値の 1 つがランダムに選択されます。

例えば、以下のマップファイルとディレクティブを使用して、 リバースプロキシ経由で複数のバックエンドサーバ間のランダムな ロードバランシングを提供できます。画像は 'static' プール内の サーバの 1 つに送信され、それ以外は 'dynamic' プールの 1 つに 送信されます。

書き換えマップファイル

##
## map.txt -- 書き換えマップ
##

static www1|www2|www3|www4
dynamic www5|www6

設定ディレクティブ

RewriteMap servers "rnd:/path/to/file/map.txt"

RewriteRule "^/(.*\.(png|gif|jpg))" "http://${servers:static}/$1"  [NC,P,L]
RewriteRule "^/(.*)"                "http://${servers:dynamic}/$1" [P,L]

画像がリクエストされ、最初のルールがマッチすると、 RewriteMap はマップファイルで 文字列 static を検索し、指定されたホスト名の 1 つを ランダムに返します。それが RewriteRule のターゲットで使用されます。

サーバの 1 つがより多く選択されるようにしたい場合 (例えば、サーバの 1 つがより多くのメモリを持ち、より多くの リクエストを処理できる場合)、マップファイルにそのサーバを 複数回記述してください。

static www1|www1|www2|www3|www4

top

dbm: DBM ハッシュファイル

MapType に dbm を使用すると、MapSource はマッピングで 使用されるキー/値ペアを含む DBM データベースファイルへの ファイルシステムパスです。これは txt マップと まったく同じように動作しますが、DBM はインデックス化されており テキストファイルはそうではないため、はるかに高速です。これにより、 目的のキーへのアクセスが高速になります。

特定の dbm タイプをオプションで指定できます:

RewriteMap examplemap "dbm=sdbm:/etc/apache/mapfile.dbm"

タイプは sdbmgdbmndbm、 または db です。 ただし、Apache HTTP Server に付属の httxt2dbm ユーティリティを 使用することを推奨します。httpd 自体のビルド時に使用されたものと マッチする正しい DBM ライブラリを使用するためです。

dbm ファイルを作成するには、まず txt セクションで 説明されているテキストマップファイルを作成し、次に httxt2dbm を実行します:

$ httxt2dbm -i mapfile.txt -o mapfile.map

その後、RewriteMap ディレクティブで結果のファイルを参照できます:

RewriteMap mapname "dbm:/etc/apache/mapfile.map"

dbm タイプによっては、共通のベース名で複数のファイルが生成される ことがあることに注意してください。例えば、mapfile.map.dirmapfile.map.pag という 2 つのファイルが存在する 場合があります。これは正常であり、RewriteMap ディレクティブではベース名 mapfile.map のみを使用 してください。

キャッシュされた検索

検索されたキーは、マップファイルの mtime (変更時刻) が 変更されるか、httpd サーバが再起動されるまで httpd にキャッシュ されます。これにより、多くのリクエストで呼び出されるマップの パフォーマンスが向上します。

top

prg: 外部書き換えプログラム

MapType に prg を使用すると、MapSource はマッピング動作を 提供する実行可能プログラムへのファイルシステムパスです。これは コンパイル済みバイナリファイル、または Python や Perl などの インタプリタ言語のプログラムです。

このプログラムは Apache HTTP Server の起動時に一度起動され、 STDINSTDOUT を通じて書き換えエンジンと 通信します。各マップ関数の検索では、キーがプログラムの STDIN に書き込まれ、その後に改行文字が続きます。 プログラムは STDIN から 1 行 (改行を含む) を読み取り、 応答を改行で終わる 1 行として STDOUT に書き込む 必要があります。キーに改行文字が含まれることはありません。 改行を含むキーが検出された場合、検索は失敗します。

対応する検索値がない場合、マッププログラムは 4 文字の 文字列 "NULL" を返して、これを示す必要があります。 この比較は大文字小文字を区別しないため、"null"、"Null" 等も 検索失敗として扱われます。その結果、マッピングプログラムが リテラル文字列 "NULL" をマップされた値として返すことは できません。

プログラムの STDERR は httpd 親プロセスから 継承されるため、プログラムが STDERR に書き込む内容は httpd 自体のエラー出力 (通常は ErrorLog) と同じ場所に記録されます。

外部書き換えプログラムは、RewriteEngineon に 設定されていないコンテキストで定義されている場合は起動されません。

デフォルトでは、外部書き換えプログラムは httpd を起動した ユーザ:グループとして実行されます。これは UNIX システムでは RewriteMap の 3 番目の 引数として username:groupname 形式でユーザ名と グループ名を渡すことで変更できます。

この機能は rewrite-map ミューテックスを使用しており、 プログラムとの信頼性のある通信に必要です。ミューテックスの メカニズムとロックファイルは Mutex ディレクティブで設定できます。

リクエスト URI 内のすべてのダッシュをアンダースコアに置き換える シンプルな例を以下に示します。

書き換え設定

RewriteMap d2u "prg:/www/bin/dash2under.py" apache:apache
RewriteRule "-" "${d2u:%{REQUEST_URI}}"

dash2under.py

#!/usr/bin/env python3
import sys

for line in sys.stdin:
    print(line.strip().replace('-', '_'), flush=True)

注意!

  • 書き換えマッププログラムはできるだけシンプルに保ってください。 プログラムがハングすると、httpd はマップからのレスポンスを 無期限に待つことになり、その結果 httpd がリクエストへの応答を 停止します。
  • プログラムでバッファリングを必ずオフにしてください。上記の Python の例では、print()flush=True を 渡すことでこれを行っています。バッファされた I/O は httpd が 出力を待つ原因となり、ハングします。
  • プログラムは 1 コピーのみで、サーバ起動時に開始されることを 忘れないでください。すべてのリクエストはこの 1 つのボトルネックを 通過する必要があります。多くのリクエストがこのプロセスを通過する 必要がある場合や、スクリプト自体が非常に遅い場合、これは 著しい速度低下を引き起こす可能性があります。
  • マッピングプログラムが終了しても、自動的に再起動されません。 以降の検索はサーバが再起動されるまで失敗します。
  • マッピングプログラムは、関連する設定ディレクティブが変更されたか どうかに関係なく、サーバの再起動 (graceful またはそれ以外) 時に 常に kill され再起動されます。シャットダウン時にプログラムには SIGTERM が送信されます。3 秒以内に終了しない場合は SIGKILL が送信されます。
top

dbd または fastdbd: SQL クエリ

MapType に dbd または fastdbd を使用すると、 MapSource は単一の引数を取り、単一の値を返す SQL SELECT 文です。

この文を実行するために、mod_dbd を正しい データベースを指すように設定する必要があります。

この MapType には 2 つの形式があります。 MapType に dbd を使用すると、各マップリクエストで クエリが実行されますが、fastdbd を使用すると データベース検索が内部的にキャッシュされます。したがって、 fastdbd はより効率的で高速ですが、サーバが 再起動されるまでデータベースの変更を検出しません。

クエリが複数の行を返す場合、結果セットからランダムな行が 使用されます。

RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"

クエリ名は SQL プリペアドステートメントのラベルとして データベースドライバに渡されるため、データベースで必要な ルール (大文字小文字の区別など) に従う必要があります。

top

まとめ

RewriteMap ディレクティブは 複数回使用できます。各マッピング関数に対して 1 つの RewriteMap ディレクティブを 使用して書き換えマップファイルを宣言してください。

ディレクトリ単位のコンテキスト (.htaccess ファイルや <Directory> ブロック) ではマップを宣言できませんが、ディレクトリ単位の コンテキストでこのマップを使用することは可能です。

翻訳済み言語:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn