Nette 在 nginx 上的反向代理别名后面

问题描述 投票:0回答:1

我有一个 Nette 应用程序在 Apache2/Debian 11 服务器上运行,运行良好。但是,我们需要使用别名将其隐藏在 nginx 代理后面。

假设我们有一个运行在 http://127.0.0.1:89/ 上的完美 Apache2 环境,并且我们希望通过设置为反向代理的 nginx 来访问它,地址为 https://example.com /应用程序/

nginx 设置如下:

  location /app/ {
    proxy_pass http://127.0.0.1:89;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto "https";
    proxy_set_header X-Forwarded-Port "443";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

虽然 Apache2 配置在代理尝试之前保持不变:

<VirtualHost *:89>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/app/www/
        <Directory /var/www/app/www/>
                Options Indexes FollowSymLinks
                AllowOverride All
                Require all granted
        </Directory>
</VirtualHost>

问题是,Nette 应用程序仍然认为它运行在没有“/app”URI 部分的路径上,因此通过重定向和链接调用生成的所有链接(包括 $basePath 模板变量)都是无效的。

我还将代理信息附加到 Nette 配置中,并且由于 nginx 实例在同一服务器上运行,因此它看起来如下:

http:
    proxy: 127.0.0.1

我尝试设置 nginx 配置以转发转发的 URI 中的 /admin 路径:

proxy_pass http://127.0.0.1:89/admin;

还尝试摆弄 Nette 路由器来过滤掉“admin/”部分(不寻找 AdminPresenter,这显然是缺失的):

$router->addRoute('[admin/]<presenter>/<action>[/<id>]', 'Homepage:default');

Nette 应用程序在尝试访问该页面时产生此错误:

TypeError: unpack() expects parameter 2 to be string, bool given in /var/www/app/vendor/nette/http/src/Http/Helpers.php:49  @  http://example.com/app/

有人可以指出我正确的方向吗?

php apache nginx reverse-proxy nette
1个回答
0
投票

好吧,回答我自己的问题,以防有人遇到同样的问题。我觉得我的解决方案有点黑客,所以请随意发布非黑客答案。

首先,我修改了nginx配置:

location /app/ {
    rewrite /app/(.*) /app/$1 break;
    proxy_pass http://127.0.0.1:89/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto "https";
    proxy_set_header X-Forwarded-Port "443";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

然后我修改了 Nette 配置以覆盖所有代理(可能实际上并不需要):

http:
    proxy: 0.0.0.0/0

我还在路由器代码中添加了“app”路由(不是作为可选前缀,而是作为常规路由):

$router = new RouteList;
$router->addRoute('app/<presenter>/<action>[/<id>]', 'Homepage:default');
$router->addRoute('<presenter>/<action>[/<id>]', 'Homepage:default');
return $router;

还修改了BasePresenter代码启动方法为:

$this->template->basePath = '/app'.$this->template->basePath;

最后我修改了.htaccess文件,将所有静态资源的URL重写为没有“app”部分的路径:

# Default Nette htaccess contents
RewriteEngine On
RewriteRule /\.|^\. - [F]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]

# Added this line under the default Nette htaccess file
RewriteRule ^app(/.*|$) $1 [NC,L]

Apache 虚拟主机保持不变。

这样,nginx 将完整的请求 URL(包括“app”)传递给 Apache,Apache 使用“app”前缀调用 Nette 路由器。路由现在工作正常,因为“应用程序”是 URL 的一部分,甚至可以被 Nette 感知(因为它实际上完全存在于请求标头中)。这会导致

$basePath
和链接/重定向正常工作。

但是,静态资源不是通过 Nette 路由器提供的,因此

app/
前缀会导致 Apache 找不到该文件并报告 404。这就是添加重写规则以删除
app/
前缀的原因静态资源的 URL。

它很hacky,但它适用于代理和非代理访问。

© www.soinside.com 2019 - 2024. All rights reserved.