読者です 読者をやめる 読者になる 読者になる

北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

Amon2のソースを読む(4)

perl+web

今日はAmon2-2.49のTriggerとPluggin。

Amon2::Trigger

クラスに対してもインスタンスに対してもフックがかけられ、それぞれ@Class::_trigger と $obj->{_trigger} を使って保存される。get_trigger_code を呼ぶと関連するハンドラを全て取得できるが、インスタンスに対して呼んだ場合はインスタンスに紐づくハンドラとそのクラスの継承ツリー上のクラスにぶら下がる全てのハンドラを得られる。ハンドラは親→子の順に並んでいる。厳密な順序に関しては、mro::get_linear_isa を使っているので現在設定されているmroの影響を受ける。

Amon2::Plugin::Web::

プラグインは $c->add_trigger でトリガを仕掛けたり、$c にメソッドを生やしたりしてYourProject::Web クラスを拡張する。


Web::FillInFormLite は$cにfillin_form メソッドを生やしてくれる。このメソッドに値をセットしておくとHTML_FILTER トリガーでフォームに値を埋めてくれる。


Amon2::Plugin::Web::NoCache はPragma とCache-Control ヘッダを設定するもので、AFTER_DISPATCH トリガーで処理される。


CSRFDefender はCSRF防止用のプラグインで、Sessionプラグインとの併用が前提*1。HTML_FILTER トリガーで<form>を見つけたら csrf_token というhiddenのinput要素を埋め込み、ここにセッションに保存されているトークンを埋め込む。BEFORE_DISPATCH トリガー内でPOSTされてきた*2トークンとセッション内のトークンを比較し、異なる場合は403ステータスで落とす。または手動で管理したい場合は、load_plugin 時の設定で no_validate_hook => 1 を渡してPOST時の自動チェックを抑止し、$cにget_csrf_defender_token と validate_csrf が生えているのでこれを使う。


HTTPSession は$cにsession() メソッドを生やし、こいつを呼ぶ度にHTTP::Session->new してインスタンスを作る。作られたインスタンスは$c->{'HTTP::Session'} に保管される。AFTER_DISPATCH トリガーで最後にresponse_filter と finalize する。HTTP::Session::Store:: と HTTP::Session::State:: はload_plugin 時に指定しておく必要がある。


PlackSessionとJSON はscaffold のコードではロードされない。PlackSessionは$cにsessionメソッドを生やして処理はPlack::Session にお任せ。


JSON は$c にrender_json を生やしてくれる。長いように見えるが、やっていることはブラウザごとのバットノウハウとセキュリティ絡みの考慮。Chrome表示の振り分けに利用されている X-Requested-With はjQuery などのフレームワークがセットする物なので、素のXMLHttpRequest を使う場合はこのヘッダをセットしてリクエストするようにしたほうがよい。

*1:正確には$c->sessionが生えてればそれでOK

*2:GET時はノーチェック