在Nginx中,我们一直试图redirect一个URL,如下所示:
http://example.com/some/path -> http://192.168.1.24
用户仍然可以在浏览器中看到原始url。 一旦用户被redirect,说他们点击链接到/section/index.html
,我们希望这做一个请求,导致redirect
http://example.com/some/path/section/index.html -> http://192.168.1.24/section/index.html
并再次保留原来的url。
我们的尝试涉及使用代理和重写规则的各种解决scheme,下面显示了使我们最接近解决scheme的configuration(请注意,这是example.com
Web服务器的Web服务器configuration)。 但是,这仍然有两个问题:
http://192.168.1.24
收到的请求URL包含/some/path
,因此无法提供所需的页面。 一旦提供页面,当您将鼠标hover在链接上时,该URL中将缺less/some/path
server { listen 80; server_name www.example.com; location /some/path/ { proxy_pass http://192.168.1.24; proxy_redirect http://www.example.com/some/path http://192.168.1.24; proxy_set_header Host $host; } location / { index index.html; root /var/www/example.com/htdocs; } }
我们正在寻找一个解决scheme,只涉及到更改example.com
上的Web服务器configuration。 我们可以改变192.168.1.24
(也是Nginx)上的configuration,但是我们想要避免这种情况,因为我们需要为通过example.com
访问的数百个不同的服务器重复这个设置。
首先,你不应该在位置块内使用root
指令,这是一个不好的做法。 在这种情况下,它并不重要。
尝试添加第二个位置块:
location ~ /some/path/(?<section>.+)/index.html { proxy_pass http://192.168.1.24/$section/index.html; proxy_set_header Host $host; }
这会将/ some / path /之后和index.html之前的部分捕获到$ sectionvariables中,然后用于设置proxy_pass目的地。 如果您需要,可以使正则expression式更具体。
您应该在proxy_pass
指令中使用URI部分。 此外,你混淆了proxy_redirect
指令的顺序参数,可能你根本就不需要它。 Nginx对此指令有合理的默认值。
在这种情况下,您的location
块可能非常简单:
location /some/path/ { proxy_pass http://192.168.1.24/; # note this slash -----------^ proxy_set_header Host $host; }
当这个斜杠被添加到一个nginx代理jenkins,你会看到“看来,你的反向代理设置是坏的”错误。
proxy_pass http://localhost:8080/; Remove this -----------------------------^
它应该阅读
proxy_pass http://localhost:8080;
您可以使用以下configuration在前端和/
后端上的/some/path/
之间build立100%的无缝映射。
请注意,这是迄今为止唯一的答案,如果浏览器发送了正确的HTTP Referer
头文件,那么也可以无缝地处理产生404 Not Found
错误的绝对path,所有这些GIF文件都应该继续加载而不需要修改底层HTML(不仅价格昂贵,而且不支持没有默认编译的附加模块)。
location /some/path/ { proxy_pass http://192.168.1.24/; # note the trailing slash! } location / { error_page 404 = @404; return 404; # this would normally be `try_files` first } location @404 { add_header Vary Referer; # sadly, no effect on 404 if ($http_referer ~ ://[^/]*(/some/path|/the/other)/) { return 302 $1$uri; } return 404 "Not Found\n"; }
您可以在https://github.com/cnst/StackOverflow.cnst.nginx.conf存储库中find完整的概念certificate和最小可行产品 。
这是一个testing运行,以确认所有边缘案例似乎工作:
curl -v -H 'Referer: http://example.su/some/path/page.html' localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location > GET /and/more.gif HTTP/1.1 > Referer: http://example.su/some/path/page.html < HTTP/1.1 302 Moved Temporarily < Location: http://localhost:6586/some/path/and/more.gif < Vary: Referer curl -v localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location > GET /and/more.gif HTTP/1.1 < HTTP/1.1 404 Not Found curl -v localhost:6586/some/path/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location -e uri > GET /some/path/and/more.gif HTTP/1.1 < HTTP/1.1 200 OK request_uri: /and/more.gif
PS如果你有很多不同的path来映射,那么你可能不想使用基于全局的map
指令,而是在location @404
的if
内进行$http_referer
的正则expression式比较。
还要注意的是, proxy_pass
中的尾部斜杠以及它所在的location
都是相当重要的 。
参考文献: