正規表現と置換だけでも万能だが、更に黒い魔術として、入力をユーザー独自のプログラムに渡して書き換えることができる、RewriteMapというのがある。
厳密には、RewriteMapは独自プログラムに渡すと言うよりは、マップテーブルを用意しておいてそこから選ぶもので、その拡張機能としてプログラムに渡すというものがあるのだろう。まあ来歴はどうでもいいが、これを使うと正規表現では書けないような妙ちきりんな書き換えもできる。例えばUTF-8エンコードされたクエリーをデコードしてSJISに変えてまたエンコードしたものにする、とか、特定のファイルが存在していたら書き換え、とか。
まず、Apacheのconfigファイルに例えばこのように書く。
RewriteEngine onRewriteLockはロックファイルの場所で、どこでも良い。但し、VirtualHostの中には置けないようなので、一番上に書く。
RewriteLock /tmp/rewritemap.lock
RewriteMap myprog prg:/usr/local/bin/url_rewriter.php
RewriteRule ^/rewrite/(.*)$ /test/${myprog:$1}
"RewriteMap プログラム名 prg:プログラムのパス"で、プログラムの場所を指定し、RewriteRule中の ${プログラム名:入力} が、プログラムによって置換される。
さて、問題のプログラムである。
どういう仕組みになっているかと言うと、mod_rewrite側は標準入力に入力を入れてきて、プログラム側は標準出力に書き換え結果を出力する。のであるが、このプログラムは、Apacheの起動時に書き換え用のプロセスが1つ立ち上がり、プロセスはずっと走りっぱなしになっているのである。アクセス毎に起動されるわけではなく、プログラム中では、(一般的には)標準入力をブロッキングI/Oで読み続けるループにする必要があるのであった。
従って例えば、url_rewriter.phpはこんな感じになる。
#!/usr/local/bin/phpmod_rewriteからは、stdinに入力内容+"\n"が来る。この入力をfgetsで取って、書き換えた結を"\n"で終端してstdoutに返す。終わったら次の入力に備える。と、こういう次第である。
<?php
$fin = fopen("php://stdin",'r');
while(!feof($fin)){
$read = fgets($fin);
$out = ここで$readに応じて書き換え処理...;
$fout = fopen("php://stdout",'w');
$out .= "\n";
fwrite($fout, $out);
fclose($fout);
}
fclose($fin);
// ※入出力はSTDINとechoを使ってもいいが、分かり易さでphp://とした。
?>
▼レンタルサーバー・VPS比較表を見る▼