Perl 如何制作mojolicous';s url_for()->;to_abs()在nginx后面返回正确的方案(http或https)
以下是我的情况: 1) Nginx监听80和443端口,并将请求转发给Mojolicious应用程序Perl 如何制作mojolicous';s url_for()->;to_abs()在nginx后面返回正确的方案(http或https),perl,nginx,reverse-proxy,mojolicious,Perl,Nginx,Reverse Proxy,Mojolicious,以下是我的情况: 1) Nginx监听80和443端口,并将请求转发给Mojolicious应用程序 upstream ssltest { server 127.0.0.1:9000; } server { listen 80; listen 443 ssl; server_name ssltest.server.com; location / { proxy_pass http://ssltest/; proxy_s
upstream ssltest {
server 127.0.0.1:9000;
}
server {
listen 80;
listen 443 ssl;
server_name ssltest.server.com;
location / {
proxy_pass http://ssltest/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
2) 在Mojolicous应用程序中,我输入以下代码:
get '/' => sub {
my $c = shift;
warn $c->url_for('/somepath')->to_abs; # HERE
$c->render(template => 'index');
};
我希望('/somepath')->的url\u返回https://ssltest.server.com/somepath
或http://.../somepath
,具体取决于我在浏览器中使用的协议但它总是返回http
(我必须创建一个绝对路径,而不是相对路径,这是有原因的)
所以,我试着在网上搜索
这个链接告诉我我可以通过自定义头X-Forward-Proto
将当前协议(http或https)传递给Mojo应用程序。但是,url_for()仍然只返回http
然后我尝试了这样的代码:
warn $c->url_for('/somepath')->to_abs->scheme(
$c->req->headers->header('X-Forwarded-Proto')
);
成功了!但是现在我必须修改代码中出现的url\u for->to\u abs
接下来,我找到了这个链接:
它使用一个钩子来修改$c->req->url->base
本身。我尝试应用它:
# change 'scheme' of request url
hook 'before_dispatch' => sub {
my $c = shift;
$c->req->url->base->scheme( $c->req->headers->header('X-Forwarded-Proto'));
};
get '/' => sub {
my $c = shift;
# url_for() seems to refer the request url to determine new url
warn $c->url_for('/somepath')->to_abs;
$c->render(template => 'index');
};
它工作得很好
现在我想知道这是否正确。是否会出现任何问题?有没有更好或最好的方法来实现我的目标
任何建议都将不胜感激。是的,这是一个好办法,但我会让它更灵活
首先,Perl中从来没有正确的方法。Mojolicious也是Perl。有时一种或多种方法比其他方法更正确。情况就是这样
您的代码很好,可以完成任务。然而,如果您决定以另一种方式部署应用程序,并且该头文件消失了,那么事情就会变得很糟糕。所以你至少应该检查一下它的存在
# change 'scheme' of request url
hook 'before_dispatch' => sub {
my $c = shift;
$c->req->url->base->scheme( $c->req->headers->header('X-Forwarded-Proto'))
if $c->req->headers->header('X-Forwarded-Proto');
};
现在,如果您使用morbo
在本地运行它,并且您没有设置头,那么事情应该仍然可以工作(假设它们首先坏了,这听起来像是我没有验证的合理假设)
要了解如何为它编写单元测试,请参阅。它从另一个角度来解决问题,但完全适用。谢谢!我担心可能会出现这样的情况:我不应该修改req->url->base->scheme
。现在我可以感觉到平静:)@gypark理论上你也应该能够配置你的nginx来为你做转换。这可能是一件明智的事情,但我不知道怎么做。莫乔利希斯在代理后不是有一个像Dancer2那样的设置来达到这个目的吗?@PerlDuck@simbabque哦,我的。。。非常感谢你。我阅读了Dancer2文档,在Mojolicious中寻找了相同的东西,发现MOJO\u REVERSE\u PROXY=1
也扮演了同样的角色。我在我的代码中尝试了它,它在没有钩子的情况下运行得非常好。(这个链接也显示了hook的用法,就像这篇文章:)@gypark这是一个有趣的巧合:-)。就在两天前,我遇到了同样的问题,因为我已经为我的Dancer2应用程序设置了一个Apache代理用于客户端证书身份验证。然后,Dancer2始终希望加载http://.../style.css
而不是https://.../style.css
等,因为“错误的”请求。uri\u base
。幸运的是,我找到了设置,很高兴听到你为Mojolicous找到了类似的设置。