首頁  >  問答  >  主體

nginx 上反向代理別名後面的 Nette

<p>我有一個在 Apache2/Debian 11 伺服器上運行的 Nette 應用程序,運行良好。但是,我們需要使用別名將其隱藏在 nginx 代理程式後面。 </p> <p>假設我們有一個運行在http://127.0.0.1:89/ 上的完美Apache2 環境,並且我們希望透過設定為反向代理的nginx 來存取它,地址為https://example.com /應用程式/</p> <p>nginx設定如下:</p> <pre class="brush:php;toolbar:false;">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; }</pre> <p>雖然 Apache2 設定在代理嘗試之前保持不變:</p> <pre class="brush:php;toolbar:false;"><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></pre> <p>問題是,Nette 應用程式仍然認為它在沒有「/app」URI 部分的路徑上運行,因此透過重定向和連結呼叫產生的所有連結(包括 $basePath 模板變數)都是無效的。 < /p> <p>我還將代理資訊附加到 Nette 配置中,並且由於 nginx 實例在同一台伺服器上運行,因此它看起來如下:</p> <pre class="brush:php;toolbar:false;">http: proxy: 127.0.0.1</pre> <p>我嘗試將 nginx 設定為轉送轉送的 URI 中的 /admin 路徑:</p> <pre class="brush:php;toolbar:false;">proxy_pass http://127.0.0.1:89/admin;</pre> <p>並且還嘗試擺弄 Nette 路由器以過濾掉“admin/”部分(不尋找 AdminPresenter,這顯然是缺少的):</p> <pre class="brush:php;toolbar:false;">$router->addRoute('[admin/]<presenter>/<action>[/<id>]', 'Homepage: default');</pre> <p>Nette 應用程式在嘗試存取該頁面時產生此錯誤:</p> <pre class="brush:php;toolbar:false;">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/</pre> <p>有人可以幫我指出正確的方向嗎? </p>
P粉953231781P粉953231781381 天前543

全部回覆(1)我來回復

  • P粉035600555

    P粉0356005552023-09-04 17:09:20

    好吧,回答我自己的問題,以防有人遇到同樣的問題。我覺得我的解決方案有點黑客,所以請隨意發布非黑客答案。

    首先,我修改了 nginx 設定:

    location /app/ {
        rewrite /app/(.*) /app/ 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(/.*|$)  [NC,L]

    Apache 虛擬主機維持不變。

    這樣,nginx 將完整的請求 URL(包括「app」)傳遞給 Apache,Apache 使用「app」前綴呼叫 Nette 路由器。路由現在運作正常,因為「應用程式」是 URL 的一部分,甚至可以被 Nette 感知(因為它實際上完全存在於請求標頭中)。這會導致 $basePath 和 links/redirect 工作。

    但是,靜態資源不是透過 Nette 路由器提供的,因此 app/ 前綴會導致 Apache 找不到該檔案並報告 404。這就是為什麼新增重寫規則的原因從靜態資源的 URL 中刪除 app/ 前綴。

    它很hacky,但它適用於代理和非代理存取。

    回覆
    0
  • 取消回覆