我在 上有一個正在運行的 Web 應用程序http://example.com/
,並且想要在 上的單獨伺服器上「安裝」另一個應用程式http://example.com/en
。上游伺服器proxy_pass
似乎可以工作,但有一個問題:
upstream luscious {
server lixxxx.members.linode.com:9001;
}
server {
root /var/www/example.com/current/public/;
server_name example.com;
location /en {
proxy_pass http://luscious;
}
}
打開時example.com/en
,我的上游應用程式返回404 not found /en
。這是有道理的,因為上游沒有路徑/en
。
是proxy_path
正確的解決方案嗎?我應該重寫“上游” /en
,以便它作為根路徑進行監聽嗎?或者是否有一個指令允許我重寫傳遞到上游的路徑?
答案1
這可能是執行您想要的操作的最有效方法,無需使用任何正規表示式:
location = /en {
return 302 /en/;
}
location /en/ {
proxy_pass http://luscious/; # note the trailing slash here, it matters!
}
答案2
我想提出一個基於正規表示式的新答案,該答案越來越受歡迎。
location ~ ^/en(/?)(.*)$ { # OOPS!
proxy_pass http://luscious/$2$is_args$args; # OOPS!
}
該解決方案乍一看似乎更可愛,但由於多種原因它是錯誤的。
上面的正規表示式將符合 的請求 uri
/enjoy
,將其重定向到/joy
上游。這真的是故意的嗎?請求
/en
不會導致任何重定向,直接從上游提供服務(幾乎就像發出了/
請求,但不完全一樣)。/en/
如果您在上游根頁面中使用相對 URI(否則,為什麼不在/en/
上游 URI 中使用前綴?),例如src="style.css"
(可能引用特定於語言的 URIurl("menu.png")
),那麼瀏覽器將請求作為/style.css
代替/en/style.css
. (或者即使你在任何地方都使用絕對 URI,如果有人相對地引用了一個不起眼的半可選資源怎麼辦?)哎呀,突然間該網站可能無法工作,但只是有時或在邊緣情況下。根據我的OP自己的答案已經提到的另一個問題的早期建議,使用正規表示式可以防止
proxy_redirect
指令的預設值是default
,將其調低為off
。這意味著,如果上游在發出Location: http://127.0.0.1:8080/en/dir/
請求時回复/en/dir
,那麼客戶端將看到這樣的內容,這顯然無法正常工作。 (對於/en
首先提示使用正規表示式的請求來說,這尤其具有諷刺意味,但這個特定的實作卻遇到了上面已經提到的另一個問題。)另外,如果您已經在使用upstream
指令,那麼如果您只是嘗試使用自訂伺服器,那麼它可能會變得格外難看,特別是如果您可能擁有多個上游伺服器 - 如何proxy_redirect
為每個伺服器提供單獨的伺服器?您proxy_redirect
也可以在 中使用正規表示式,甚至可以匹配任何主機,但是如果您決定將來提供跨域重定向怎麼辦?
要嘗試使用基於正規表示式的單一位置來解決上述一些問題,我們可以執行以下操作(請注意,proxy_pass
我們還必須從基於 - 的指令中刪除對伺服器的引用upstream
,以使其proxy_redirect
更加簡單):
location ~ ^/en/?((?<=/).*)?$ {
location = /en { return 302 /en/; }
proxy_pass http://127.0.0.1:8080/$1$is_args$args;
proxy_redirect http://127.0.0.1:8080/ /en/;
}
所以,如果你問我,具有兩個兄弟頂級位置的原始解決方案與透過正規表示式路線將自己挖進兔子洞相比,這仍然是一個更好的主意。
答案3
所以,我找到了在 stackoverflow 上回答:
upstream luscious {
server lixxxx.members.linode.com:9001;
}
server {
root /var/www/example.com/current/public/;
server_name example.com;
location ~ ^/en(/?)(.*) {
proxy_pass http://luscious/$2;
}
}
基本上:將正規表示式傳遞到位置並將 backref 傳遞到 proxy_pass url。
答案4
我嘗試了上面接受的解決方案,但發現它導致所有 CSS 和 JS 資源出現危險的重定向。最後,我從 LinuxServer SWAG Nginx 設定的完成方式中找到了靈感。你可以找到他們這裡。看一眼pihole.subfolder.conf.sample
。
因此,我的解決方案如下所示:
location /en {
return 302 $scheme://$host/en/;
}
location ^~ /en/ {
set $upstream_app lixxxx.members.linode.com;
set $upstream_port 9001;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
rewrite /en(.*) $1 break;
}