在 Plack 中构建调度程序
Plack::App::URLMap 有一个替代方案,称为Plack::App::HostMap,它的查找速度更快,因为它在内部使用哈希,而不是数组。所以没有迭代进行。它只是进行哈希查找,而且在 Perl 中非常快。
权衡是现在您只能使用常量主机名。因此,如果您的列表是这样的:
example.org
example.com
example.de
example.am
example.cx
或使用以下子域:
one.example.org
two.example.org
three.example.org
four.example.org
five.example.org
six.example.org
那么这就完美了。另一方面,我不确定它是否支持也具有恒定路径部分的 URL,例如http://foo.example.org/bar
,其中有很多foo
s,但它们都共享安装应用程序的相同/bar
路径。该模块根本没有任何测试,我无法尝试。如果您查看这些更改,至少有一个人建议了附加功能,因此作者以外的其他人正在使用它。
要使用它,您可以从 Plack::Builder 切换到使用 Plack::App::HostMap 作为您调用方法的应用程序。
use Plack::App::HostMap;
# set up %apps (e.g. foo.example.org, bar.example.org)
my $host_map = Plack::App::HostMap->new;
for my $site (@sites) {
$host_map->map( $site => $apps->{$site} );
}
您并没有告诉我们/
路由应该做什么,但本质上它还需要一个主机。如果你的服务器有很多主机名,那么它们都会响应这个请求。这就是你想要做什么的全部想法。但是主机名是干什么用的/
?所以最好的办法是为sub { ... }
斜线应用程序添加一个带有真实主机名的附加行。也许那是一个控制面板或其他东西。因此,将其连接到实际的 URL。
$host_map->map( "example.org" => sub { ... } );
用于执行此操作的 Web 框架
单例在这里并不是真正的问题。似乎不可能让 Dancer2 使用相同的配置或环境加载不同的配置或环境。对于这个用例,我没有尝试过 Mojo、Web::Simple 或 Catalyst。
我确实在 D2 上做了很多尝试,我得到的最接近的是/
在 MyApp 和这个 PSGI 应用程序中有一条路线。请注意,这不起作用。
use Plack::Builder;
my $builder = Plack::Builder->new;
foreach my $name (qw/development production/) {
$builder->mount(
"/$name" => builder {
eval <<"APP";
package MyApp::$name {
use Dancer2;
use MyApp with => { environment => "$name" };
}
APP
"MyApp::$name"->to_app;
}
);
}
$builder->to_app;
dancer2 -a MyApp
它使用使用和未更改的环境文件生成的默认骨架。来自 Plack 的调度有效,但 Dancer2 感到困惑。
HTTP::Server::PSGI: Accepting connections at http://0:5000/
[MyApp::production:4896] core @2017-02-10 02:14:42> looking for get / in /home/julien/perl5/perlbrew/perls/perl-5.20.1/lib/site_perl/5.20.1/Dancer2/Core/App.pm l. 35
[MyApp::production:4896] core @2017-02-10 02:14:42> Entering hook core.error.init in (eval 49) l. 1
[MyApp::production:4896] core @2017-02-10 02:14:42> Entering hook core.error.before in (eval 49) l. 1
[MyApp::production:4896] core @2017-02-10 02:14:42> Entering hook core.error.after in (eval 49) l. 1
127.0.0.1 - - [10/Feb/2017:02:14:42 +0100] "GET /production/ HTTP/1.1" 404 456 "-" "curl/7.47.0"
[MyApp::development:4896] core @2017-02-10 02:18:06> looking for get in /home/julien/perl5/perlbrew/perls/perl-5.20.1/lib/site_perl/5.20.1/Dancer2/Core/App.pm l. 35
[MyApp::development:4896] core @2017-02-10 02:18:06> Entering hook core.error.init in (eval 49) l. 1
[MyApp::development:4896] core @2017-02-10 02:18:06> Entering hook core.error.before in (eval 49) l. 1
[MyApp::development:4896] core @2017-02-10 02:18:06> Entering hook core.error.after in (eval 49) l. 1
127.0.0.1 - - [10/Feb/2017:02:18:06 +0100] "GET /development HTTP/1.1" 404 457 "-" "curl/7.47.0"
这个想法是使用相同的包文件并将其子类化以在 via 中获取不同的配置with
。
但是,可以一遍又一遍地在循环中定义相同的应用程序。您可能可以使用代码引用将路由处理程序移出,例如get '/' => \&main::get_slash
,其中sub get_slash
不在eval
.
use Plack::Builder;
my $builder = Plack::Builder->new;
foreach my $name (qw/development production/) {
$builder->mount(
"/$name" => builder {
eval <<"APP";
package MyApp::$name {
use Dancer2;
use Data::Printer;
set environment => "$name";
get "/" => sub { np(config) }
}
APP
"MyApp::$name"->to_app;
}
);
}
$builder->to_app;
该字符串eval
并不像这里看起来那样邪恶,因为该代码仅在启动时运行。D2 将在内部跟踪您在此处以编程方式创建的所有应用程序。但我不知道它的性能如何。