@kyanny's blog

My life. Opinions are my own.

HTTPx::Dispatcher の練習

HTTPx::Dispatcher の使い方を勉強した。ごちゃごちゃ試行錯誤して、使い方がわかったので、動かすための最小限のコードを整理して github にあげた。

GitHub - kyanny/httpx-dispatcher-practice: HTTPx::Dispatcher practice

参考になったソース

mobirc

どう書くとどう動くのか例

connect '' => { controller => 'Root', action => 'index' };

これは、 $req->uri->path eq '/' の場合にマッチするルール(HTTPx::Dispatcher が内部で '/' を '' に変換している)。 $rule は、

$rule = MyApp::Dispatcher->match($req);
$rule = {
    controller => 'Root',
    action => 'index',
}

こんな構造になっている。なので、例えばコントローラが MyApp::Controller:: というネームスペースを持ってるなら、 'MyApp::Controller::' . $rule->{controller} とか、文字列でクラス名を作ってやって require なり use なりしてやる(そこは HTTPx::Dispatcher や HTTP::Engine が面倒を見てくれない部分なのでこちらで好きにやる)。

connect 'foo/bar' => { controller => 'Foo', action => 'bar' }'

これは、 $req->uri->path eq '/foo/bar' の場合にマッチするルール。それ以外のパスの場合はマッチしない。 $rule は、

$rule = MyApp::Dispatcher->match($req);
$rule = {
    controller => 'Foo',
    action => 'bar',
}

こんな構造になっている。

connect 'hoge/:action' => { controller => 'Hoge' };

これは、 $req->uri->path =~ m{^/hoge/.*} みたいな場合にマッチするようだ。 action を明示しないで :action と書くことで、コントローラは明示したいがアクションはそのコントローラのものなら何でも良い、という大ざっぱなルールを指定できるっぽい。 $rule は、

$rule = MyApp::Dispatcher->match($req);
$rule = {
    controller => 'Hoge',
}

ここまでは決まってて、リクエストされたパスが '/hoge/hoge' ならば action => 'hoge' になるし、パスが '/hoge/moe' ならば action => 'moe' になる。で、 MyApp::Controller::Hoge に sub hoge {} ないし sub moe {} が実装されていればそれを呼ぶ(実際に $controller->$action($req) みたいにして呼ぶコードはハンドラーの中に自分で書く)。パスが '/hoge/fuga' だったりすると sub fuga {} が実装されてないのでエラーになる。

POD には connect ':controller/:action/:id' と、アクションの次に id も指定できる風に書いてあるので、そこも使うと /hoge/moe?id=12345 みたいなのをもっと綺麗に書けるってことだと思うけど、そこまではまだ試していない。