Perl 如何制作mojolicous';s url_for()->;to_abs()在nginx后面返回正确的方案(http或https)

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

以下是我的情况:

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_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找到了类似的设置。