该普拉克::生成器允许挂接多个主机,例如一些如下面的代码片段:
my @sites = load_site_names();
my $apps;
for my $site (@sites) {
$apps->{$site} = Some::PsgiFramework::MyApp->new( config => get_config($site) );
}
use Plack::Builder;
builder {
for my $site (@sites) {
mount "$site" => $apps->{$site};
}
mount '/' => sub { ... };
}
Run Code Online (Sandbox Code Playgroud)
例如
load_site_names返回站点的列表一样http://example.com,http://some.other.site.com...Some::PsgiFramework::MyApp我完全需要以上内容 - 需要开发一个简单的网络应用程序,该应用程序应该部署在不同(低流量)站点的数据库中,并且不希望为每个站点设置不同的PSGI服务器.
然而,Plack本身的作者说(在Plack :: Request中)
请注意,此模块旨在供Plack中间件开发人员和Web应用程序框架开发人员而非应用程序开发人员(最终用户)使用.
使用Plack :: Request直接编写Web应用程序当然是可行的,但不推荐:它就像使用mod_perl的Apache :: Request那样:但是程度太低.
如果您正在编写Web应用程序而不是框架,那么建议您使用一个支持PSGI的Web应用程序框架(http://plackperl.org/#frameworks),或者查看HTTP :: Engine等模块在PSGI之上提供更高级别的请求和响应API.
这就是问题所在.
我在MetaCPAN中检查了许多不同的基于PSGI的框架.并且AFAIK每个都是基于单一的,例如,不允许写入应用程序可以多次共享(安装)同一个不同的站点app.psgi.
所以问题是:
app.psgi?Just Another My Own PSGI Framework?(老实说,我没有检查催化剂 - 因为它太重了)Plack::App::URLMap 有一个替代方案,称为Plack::App::HostMap,它的查找速度更快,因为它内部使用散列,而不是数组。所以没有进行迭代。它只是进行哈希查找,而这些在 Perl 中速度非常快。
代价是现在您只能使用常量主机名。因此,如果您的列表是这样的:
example.org
example.com
example.de
example.am
example.cx
Run Code Online (Sandbox Code Playgroud)
或者使用子域,例如:
one.example.org
two.example.org
three.example.org
four.example.org
five.example.org
six.example.org
Run Code Online (Sandbox Code Playgroud)
那么这就完美了。另一方面,我不确定它是否支持也具有恒定路径部分的 URL,例如http://foo.example.org/bar,其中有很多foos,但它们都共享/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} );
}
Run Code Online (Sandbox Code Playgroud)
您没有告诉我们该/路线应该做什么,但本质上它还需要一个主机。如果您的服务器有很多主机名,那么所有主机名都会响应此请求。这就是你想做的事情的全部想法。但是主机名的用途是什么/?因此,最好的办法是为sub { ... }斜线应用程序添加一条带有真实主机名的附加行。也许那是一个控制面板之类的。所以将其连接到实际的 URL。
$host_map->map( "example.org" => sub { ... } );
Run Code Online (Sandbox Code Playgroud)
单例并不是真正的问题。似乎不可能让 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;
Run Code Online (Sandbox Code Playgroud)
它使用使用未更改的环境文件生成的默认框架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"
Run Code Online (Sandbox Code Playgroud)
这个想法是使用相同的包文件并将其子类化以在 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;
Run Code Online (Sandbox Code Playgroud)
该字符串eval并不像看起来那么邪恶,因为该代码仅在启动时运行。D2 将在内部跟踪您在此处以编程方式创建的所有应用程序。但我不知道它的性能如何。