Yappo::タワシ このページをアンテナに追加 RSSフィード

2009-01-27

HTTP::Engine::Request のメソッド拡張を Middleware で行わないとき

package HTTP::Engine::Middleware;
use Mouse;

my %middleware_heap;

sub attribute {
    my($class, $req, $attribute) = @_;
    ($middleware_head{$req+0} || {})->{$attribute};
}

sub set_attribute {
    my($class, $req, $attribute, $value) = @_;
    $middleware_head{$req+0}->{$attribute} = $value;
}

しといて、設定は

package HTTP::Engine::Middleware::MobileAgent;
use HTTP::Engine::Middleware;
use HTTP::MobileAttribute;
before {
    my $req = shift;
    HTTP::Engine::Middleware->set_attribute(
        $req => 'mobile_attribute',
        HTTP::MobileAttribute->new($req),
    );
    $req;
};
1;

呼び出しは、どこでも

sub handle_request {
    my $req = shift;
    HTTP::Engine::Middleware->attribute( $req => 'mobile_attribute' )->is_docomo;
}

できるようにするか

package HTTP::Engine::Middleware;
use Mouse;

# ...

sub import {
    # ...
    *{"$caller\::install_attribute"} = sub {
        my($name, $code) = @_;
        *{"middleware\::$name"} = $code;
    };
}

{
    package middleware;

}

しといて、設定は

package HTTP::Engine::Middleware::MobileAgent;
use HTTP::Engine::Middleware;
use HTTP::MobileAttribute;

my $attribute;
before {
    my $req = shift;
    $attribute = HTTP::MobileAttribute->new($req);
    $req;
};

install_attribute mobile_attribute => sub { $attribute };

1;

呼び出しは、どこでも

sub handle_request {
    my $req = shift;
    middleware->mobile_attribute->is_docomo;
}

とできる方法を思いついた。


全者は助長だが名前空間汚染せず、後者は割とシンプルだがmiddlewareって名前空間を汚染する。

いっちばんいいのは HTTP::Engine::Request にメソッド生やすのかなーともおもうが、どうなんだろ。


ちなみに HTTP::Engine::Middleware->impot は caller の名前空間にMiddlewareって階層があった時だけfunction importする。

呼び出し元の名前によって、 middleware の定義をさせるか、それを使う側になるかが変わる方式。

もしくは use HTTP::Engine::Middleware::Declare; でもいいのかもしれないが、実際書いてみてしっくり来るほうかなぁ。

前者のが分かりにくいmagicになるが。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/yappo/20090127/1233003333