新しいblogに移行しました

新ブログ "All Yout Bugs Are Belong To Ass" に移行しました!

2011-03-04

[Perl]plackアプリとAttribute::Handlersの相性は悪い

先日作ったRouter::Simple::Attributeを使ってPlackベースのWAFを作ろうとしたのですが、どういうわけかrouterの中身がカラッポになってしまい、ちっともまともに動作してくれませんでしたorz

で、よくよく調べてみると、どうやらPlack::SandboxとAttribute::Handlersの相性がよろしくない模様でした。

検証用コード - eg/sample.pl

まあ幾つかツッコミどころが有りますけど、問題の本質とは関連がないものばかりの筈なのでスルー。
use warnings;
use strict;
use lib qw( ../lib ./lib );
use Attribute::Handlers;
use Router::Simple;
use Data::Dumper;

my $router;

BEGIN {
    $router = Router::Simple->new();
}

sub Path :ATTR {
    warn Dumper( @_ );
    my $path = $_[4];
    my $code = $_[2];
    $router->connect( $path, { code => $code } );
}

sub myapp : Path(/) { 
    warn Dumper( @_ );
    [ 200, ['text/html'], ['Hello, world!'] ];
}

warn Dumper( $router, __PACKAGE__ );

sub {
    my $env = shift;
    if ( my $p = $router->match( $env ) ) {
        $p->{ code }->( $p );
    }
    else {
        [404, [], ['no']];
    }
};

perlコマンドから直接実行して見た場合

$ perl eg/sample.pl 
Useless use of reference constructor in void context at eg/sample.pl line 35.
$VAR1 = 'main';
$VAR2 = \*::myapp;
$VAR3 = sub { "DUMMY" };
$VAR4 = 'Path';
$VAR5 = '/';
$VAR6 = 'CHECK';
$VAR7 = 'eg/sample.pl';
$VAR8 = 24;
$VAR1 = bless( {
                 'routes' => [
                               bless( {
                                        'pattern_re' => qr/(?-xism:^\\/$)/,
                                        'pattern' => '/',
                                        'capture' => [],
                                        'dest' => {
                                                    'code' => sub { "DUMMY" }
                                                  },
                                        'name' => undef,
                                        'on_match' => undef
                                      }, 'Router::Simple::Route' )
                             ]
               }, 'Router::Simple' );
$VAR2 = 'main';
一応、Pathアトリビュートのトリガが引かれていることが確認できてます。

plackupした場合

では、今度はeg/sample.plをplackupで起こしてみます。
$ plackup eg/sample.pl 
$VAR1 = bless( {
                 'routes' => []
               }, 'Router::Simple' );
$VAR2 = 'Plack::Sandbox::eg_2fsample_2epl';
HTTP::Server::PSGI: Accepting connections at http://0:5000/
こんな感じで、Pathアトリビュートのトリガが引かれません。

誰かおしえてください

そんなわけで、plackupからでも問題なく使用できるメソッドアトリビュートハンドラを探しています。
どなたかご存知の方、教えてください。よろしくお願いしますm(_ _)m


教えていただきました!

Twitterで、色々な方にご教示頂きました!この場を借りて、改めて御礼申し上げます。
まとめると、僕は「Attribute病」:) に罹患していたらしく、

・PSGIアプリではINIT/CHECKなどが呼ばれないため、アトリビュートはほぼ動かない。
・アトリビュート使うと、第3者からみて「何してるかわからないコード」になってしまい、おすすめできない。
・Attr::Handlers sucks, and Perl5 attribute sucks too. で FA。

ということらしいです。従って結論は

アトリビュートを使うのはお止しなさい

0 件のコメント: