3

拥有下一个简单的 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 / ),所以幕后有一些东西。

有人可以解释一下吗?

4

1 回答 1

4

查看源代码有助于了解发生了什么:

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;
于 2013-05-27T16:25:40.080 回答