我正在寻找一种可靠的方法来配置在/ app下的Apache反向代理后面运行的Mojolicious,这样url_for('/foo')
实际上返回/app/foo
而不仅仅是/foo
(否则所有的链接都会被破坏).
该文档显示了/下所有内容的反向代理示例.但这不是我需要的,因为应用程序应该在/ app下.
谈及ProxyPass / http://localhost:8080/
到ProxyPass /app http://localhost:8080/
会造成问题,因为/app
前缀会从应用程序生成的所有URL会丢失.
该文档还有一个关于重写的部分,其中有一个before_dispatch钩子的示例,它将获取请求URL的第一部分并将其用作基础.这需要ProxyPass /app http://localhost:8080/app/
在Apache配置中将前缀附加到ProxyPass URL(带有斜杠),这在该页面上似乎没有提及,但可能不需要("移动第一部分并从路径到基础的斜杠)路径")因为它很明显.这使得调用成为可能(http://localhost/app/page
转换为http://localhost:8080/app/page
'app'被钩子删除),url_for('/foo')
返回'/app/foo'
(http://localhost/app/foo
),所以链接将是正确的(在ProxyPass规则中没有尾随斜杠,这将使得/apppage/foo
).
但是,在此示例中,URL修改始终在生产模式(if app->mode eq 'production'
)中进行.所以直接调用后端服务器(http://localhost:8080/testpage
)将不再起作用,因为所有的URL都会被破坏.
所以我想,我会检查是否X-Forwarded-For
设置了标头(通过mod_proxy_http),这将始终设置为反向代理请求.并且由于Apache mod_proxy文档提到可能已经在客户端请求中设置了此标头(并且最终包含多个值),我首先将其从请求中删除 - 因为发送此标头的客户端不应该导致该URL基础修改.
Apache VirtualHost配置:
# ProxyPreserveHost: Mojo::URL::to_abs() not 127.0.0.1 ProxyPreserveHost On# ProxyPass: prefix pass-thru ProxyPass http://localhost:3000/app/ # RequestHeader: must not be set externally RequestHeader unset X-Forwarded-For
在Mojolicious启动中的钩子():
$self->hook('before_dispatch' => sub { my $c = shift; my $behind_proxy = !!$c->req->headers->header('X-Forwarded-Host'); if ($behind_proxy) { push @{$c->req->url->base->path->trailing_slash(1)}, shift @{$c->req->url->path->leading_slash(0)}; $c->req->url->path->trailing_slash(0) # root 404 unless @{$c->req->url->path->parts}; } });
这看似有效......
问题:我的方法在"现实世界"中是否可靠地工作还是有缺陷?
编辑:通过反向代理
请求根地址(http://localhost:3000/app/
)总是导致错误404.所以我添加了两行来在这种情况下关闭尾部斜杠.由于我在文档中找不到,可能有更好的方法.