Amon2でコントローラー(Dispatcher)が動く前に処理を入れたい。

元となるソース(というか、修正するファイル)は、以前作成した(Amon2で$c->render()を自動で呼ぶようにしてみた。)のMyApp::Web
気分的には、Catalystのautoに近い挙動を目指す。

package MyApp::Web;

# dispatcher
use MyApp::Web::Dispatcher;
sub dispatch {
    my $c = shift;

    my $res = undef;
    my $env = $c->request->env;
    my ($method) = MyApp::Web::Dispatcher->router->match( $env->{REQUEST_METHOD}, $env->{PATH_INFO} );
    eval {
        # autoを呼ぶ
        $res = $method->{'class'}->auto($c);
    };
    # レスポンスを持っている(autoでリダイレクトとか)
    return $res if ( ref $res eq 'Amon2::Web::Response');

    # コントローラーを呼ぶ
    $res = MyApp::Web::Dispatcher->dispatch($c);
    # レスポンスを持っている
    return $res if ( ref $res eq 'Amon2::Web::Response');

    # jsonを返す場合(Amon2::Plugin::Web::JSON)
    if ( exists $c->stash->{'json'} ) {
        return $c->render_json( $c->stash->{'json'} );
    }

    # htmlを返す場合
    my $template = '';
    if ( $c->stash->{'template'} ) {
        # templateを手動で指定
        $template = $c->stash->{'template'};
    }
    else {
        # templateを自動セット
        my $path = $method->{class} .'/' . $method->{method};
        $path =~ s/MyApp::Web::C:://;
        $path =~ s/\:\:/\//g;
        $path = lc $path;
        $template = $path . '.tt';
    }

    return ( $c->render($template, $c->stash ) or die "response is not generated" );
}

1;

“Class”->auto($c);を追加

これで、コントローラーを呼ぶ前に同名のClassに書いたautoメソッドが呼ばれる。

コントローラーのサンプル

package MyApp::Web::C::User;

sub auto {
    my ( $class, $c ) = @_;

    # 事前処理(Authチェックとか)
}

sub index { }
sub edit { }

1;

追記

もしかして

__PACKAGE__->add_trigger(BEFORE_DISPATCH => sub { my $c = shift; ... });

をうまく使えば簡単にできる気がした。