Plack::Builder - последняя строка не использует mount - сообщение об ошибке
Имея следующее простое приложение Plack:
use strict;
use warnings;
use Plack::Builder;
my $app = sub {
return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
};
builder {
foreach my $act ( qw( /some/aa /another/bb / ) ) {
mount $act => $app;
}
};
ошибка возврата:
WARNING: You used mount() in a builder block, but the last line (app) isn't using mount().
WARNING: This causes all mount() mappings to be ignored.
at /private/tmp/test.psgi line 13.
Error while loading /private/tmp/test.psgi: to_app() is called without mount(). No application to build. at /private/tmp/test.psgi line 13.
но следующий строительный блок в порядке.
builder {
foreach my $act ( qw( /some/aa /another/bb / ) ) {
mount $act => $app;
}
mount "/" => $app;
};
Я понимаю, что говорит руководство Plack::Builder
ПРИМЕЧАНИЕ. После того, как вы используете mount в своем коде компоновщика, вы должны использовать mount для всех путей, включая корневой путь (/).
Но в for
петля у меня есть /
смонтировать как последний: qw( /some/aa /another/bb / )
так что что-то здесь за сценой.
Кто-нибудь может объяснить, пожалуйста?
1 ответ
Взгляд на исходный код поможет понять, что происходит:
sub builder(&) {
my $block = shift;
...
my $app = $block->();
if ($mount_is_called) {
if ($app ne $urlmap) {
Carp::carp("WARNING: You used mount() in a builder block,
Так, builder
это просто подпрограмма, а ее аргумент является блоком кода. Этот блок кода оценивается, и результат заканчивается $app
, Однако в вашем коде результатом оценки является пустая строка, которая является результатом завершающей foreach
цикл:
$ perl -MData::Dumper -e 'sub test{ for("a", "b"){ $_ } }; print Dumper(test())'
$VAR1 = '';
поскольку mount foo => $bar
"просто" синтаксический сахар, который даже становится трудно читать в таких случаях, как ваш, я предлагаю вам сделать маленький шаг к голому металлу, пропустить синтаксический сахар и напрямую использовать Plack::App::URLMap:
use strict;
use warnings;
use Plack::App::URLMap;
my $app = sub {
return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
};
my $map = Plack::App::URLMap->new;
foreach my $act ( qw( /some/aa /another/bb / ) ) {
$map->mount( $act => $app );
}
$map->to_app;