ありゃ。本当にイチハラヒロコだったらしい。
あげられている書籍の 「この人ゴミを押しわけて、はやく来やがれ、王子さま。」 はかなり面白いので、興味のある人は是非。
mod_ruby の真価は ruby script が早く動くことではなく apache の挙動を ruby で制御できることだ。 ……というわけで今まで mod_rewrite でやっていた URL 書き換えを mod_ruby のハンドラでやってみることにした。
と、思い立ったのは良いんだけど オフィシャル 見てもドキュメントが全然無い。 仕方ないのでソースと mod_perl のサイトを読む。 URL Translation phase でコードを実行するには RurbyTransHandler ディレクティブに translate_uri メソッドを持つオブジェクトを 指定すれば良いみたい。
自分で調べた部分は Wiki に勝手に追加しといた。
わざわざ singleton を使わなくてもclass のオブジェクトを そのまま渡せばいいや、と言うことでこんな風に。
class SugiTDiaryRewriter
BASE_URL = "/diary/" # must end with /
def self.translate_uri(r)
if r.uri !~ /^#{BASE_URL}/
return Apache::DECLINED
elsif r.uri =~ %r[^#{BASE_URL}(\d{6,})(-\d+)?.html?$]
new_uri = "#{BASE_URL}?date=#{$1}#{$2}"
elsif r.unparsed_uri =~ %r[^#{BASE_URL}(?:index\.cgi)?\?(?:.*&to=)?(\d{6,})]
# HNS style
new_uri = "#{BASE_URL}?date=#{$1}"
end
if new_uri
r.internal_redirect(new_uri)
return Apache::DONE
end
return Apache::DECLINED
end
end
このコードを呼ぶために httpd.conf の VirtualHost 内 に以下を追加すればOK。
RubyRequire /etc/apache2/vhosts/sugi/tdiary-rewrite.rb RubyTransHandler SugiTDiaryRewriter
SugiTDiaryRewriter と言う定数はクラスそのものなので、 クラスメソッドの translate_uri が正しく呼ばれます。
うう。後で気づいたけど、英語の方にはちゃんとあった ……。ソースの doc ディレクトリに入ってるのもこれか。
とりあえず debian package にこのドキュメント入れて欲しい と言うのをBTSに出しておく。
もう一つついでにメモ。
上の話は内部リダイレクトを使っているけど、例えば Alias ディレクティブの様にファイルシステムへの マッピングを書きたい時もある。例えば以下のように。
Alias /diary /home/sugi/www/sugi/tdiary
このAliasと同じ事をするには、r.filename に代入してやればいい。 この辺は mod_perl と同じなので、 perl のドキュメント当たった方が早そうですね。
class MyAlias
def self.translate_uri(r)
if r.uri =~ %r[^/diary(.*)]
r.filename = "/home/sugi/www/sugi/tdiary#{$1}"
return Apache::OK
end
return Apache::DECLINED
end
end