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)
のようになる。