Plack::Builder は Middleware をラップしてくれたり、 Plack::App::URLMap を使ったマッピングを担ってくれる。
通常は次のように使う
use Plack::Builder;
use Plack::Session::Store::File;
my $app = sub { ... };
my $app2 = sub { ... };
builder {
enable "Session",
store => Plack::Session::Store::File->new(...);
mount "/foo" => $app2;
mount "/" => $app;
};
例
Twitter の OAuth をサービスのログインに使いたいとする。この場合、コールバックURLを指定する必要があるが、ログイン処理は /login 以下にまとめるのが良いだろう。
例えば、
http://localhost:5000/login http://localhost:5000/login/callback
のようなパスにマップしたいときは、次のように builder をネストさせる
use Plack::Builder;
use Plack::Session::Store::File;
builder {
enable "Session",
store => Plack::Session::Store::File->new(...);
mount '/login' => builder {
mount '/callback' => sub {
my $env = shift;
return [200, [], ["in callback"]];
};
mount '/' => sub {
my $env = shift;
return [200, [], ['<a href="...">Login</a>']];
};
};
mount '/' => sub { ... };
};
この例では "/login" にアクセスすると、 mount された "/login" の中で mount された "/" が呼ばれる。
"/login/callback" にアクセスすると、 mount された "/login" の中で mount された "/callback" が呼ばれる。
builder の注意点
- mount を一度でも使った場合は、 fallback として "/" を mount する必要がある($app を最後に書くだけではダメ)
- mount の第一引数は "/" から始まり、前方一致で判定される。ただし、最初の "/" から次の "/" までは完全一致している必要がある。
-
- この例の場合、 "/loginx" にアクセスされた場合は一番外側の builder で mount された "/" に fallback する。
- "/login/callbackx" にアクセスされた場合は mount された "/login" の中で mount された "/" に fallback する。
$env の注意点
$env->{PATH_INFO} と $env->{SCRIPT_NAME} は、 Plack::App::URLMap によって、その coderef の位置する部分に適する形に書き換える。
つまり、
(snip)
mount '/login' => builder {
mount '/callback' => sub {
my $env = shift;
# $env->{PATH_INFO} eq ''
# $env->{SCRIPT_NAME} eq '/login/callback'
};
mount '/' => sub {
my $env = shift;
# $env->{PATH_INFO} eq ''
# $env->{SCRIPT_NAME} eq '/login'
};
};
(snip)
のようになる。