@kyanny's blog

My life. Opinions are my own.

mod_rewrite の RewriteMap の Apache 内部関数の使い方

mod_rewrite には RewriteMap というディレクティブがある。その名の通り、ある入力パターンを対応する値と置き換えるもので、外部のプログラム (rewrite.pl みたいな)を指定して使うことが多かったけど、 Apache 内部関数というのも指定できる。

# 内部関数
MapType: int, MapSource: 内部 Apache 関数

ソースとして、内部 Apache 関数を使うこともできます。 現時点ではエンドユーザが自分用に独自のものを作ることはできませんが、 以下のものが用意されています。

* toupper:
見つかったキーをすべて大文字に変換する。
* tolower:
見つかったキーをすべて小文字に変換する。
* escape:
見つかったキーの中の特殊文字を 16 進エンコーディングに変換する。
* unescape:
見つかったキーの中の 16 進エンコーディングを特殊文字に戻す。

http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html#RewriteMap

どういうときに使うんだろうな、と思いつつ使う機会がなかったけど、さっき使う機会があった。

http://blog.livedoor.com/t/%C6%FC%B5%AD

この URL にアクセスしてきたら 410 Gone を返すようにしたいとする。エスケープされてる部分は EUC-JP で「日記」という文字列。

これを、以下のような RewriteRule でマッチさせる。

RewriteMap gone int:escape
RewriteCond ${gone:%{REQUEST_URI}} ^/t/%C6%FC%B5%AD$ [NC]
RewriteRule ^/ - [G,L]

RewriteLog を出力して書き換え処理を眺めていると、エスケープされてない REQUEST_URI に対してパターンマッチしているので、エスケープ済みの文字列にはマッチしない。そこで、 escape 関数でエスケープした REQUEST_URI とエスケープ済みの文字列をマッチさせるという寸法。

いままで、そういう non-ascii な文字列に対してマッチングさせたりするときは外部プログラムをかますしか方法がないかと思っていたけど、複雑でない文字列マッチングならこれで十分そう。

・・・しかし、ものはためしで以下のように書いても難なく動いてしまったので、上の書き方は単なる自己満足だった・・・。(ただし、下のように書く場合はファイルの文字エンコーディングは EUC-JP でなければならない)

RewriteCond %{REQUEST_URI} ^/t/日記$
RewriteRule ^/ - [G,L]