在 Nginx 中我们尝试重定向 URL 如下:
http://example.com/some/path -> http://192.168.1.24
用户在浏览器中仍会看到原始 URL。一旦用户被重定向,比如他们点击了 的链接/section/index.html
,我们希望它发出一个导致重定向的请求
http://example.com/some/path/section/index.html -> http://192.168.1.24/section/index.html
并再次保留原始 URL。
我们尝试了各种使用代理和重写规则的解决方案,下面显示了最接近解决方案的配置(请注意,这是 Web 服务器的 Web 服务器配置example.com
)。但是,这仍然存在两个问题:
- 它没有正确地执行重写,因为 Web 服务器收到的请求 URL
http://192.168.1.24
包含所需的页面/some/path
,因此无法提供所需的页面。 当您将鼠标悬停在页面已提供的链接上时,
/some/path
URL 中缺少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; } }
我们正在寻找一种仅涉及更改 Web 服务器配置的解决方案example.com
。我们能够更改配置192.168.1.24
(也包括 Nginx),但是我们希望尽量避免这种情况,因为我们需要对数百台通过代理访问的不同服务器重复此设置example.com
。
答案1
首先,您不应该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 之前的部分捕获到 $section 变量中,然后使用该变量设置 proxy_pass 目标。如果需要,您可以使正则表达式更具体。
答案2
您应该使用 URI 部分proxy_pass
指令。此外,您混淆了proxy_redirect
指令的顺序参数,可能您根本不需要它。Nginx 为该指令提供了合理的默认值。
在这种情况下,你的location
块可能非常简单:
location /some/path/ {
proxy_pass http://192.168.1.24/;
# note this slash -----------^
proxy_set_header Host $host;
}
答案3
/some/path/
您可以使用以下配置在前端和/
后端之间实现 100% 无缝映射。
请注意,这是迄今为止唯一的答案,404 Not Found
只要Referer
浏览器发送了正确的 HTTP 标头,它就可以无缝地处理产生错误的绝对路径,因此,所有这些 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存储库。
以下进行测试以确认所有边缘情况均有效:
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 如果您有很多不同的路径需要映射,那么您可能不想$http_referer
在 withinif
中进行正则表达式比较location @404
,而是想要使用基于全局的map
指令。
proxy_pass
还请注意, 以及它所location
包含的中的尾部斜杠,根据相关答案非常重要。
参考:
答案4
当该斜线添加到 nginx 代理的 jenkins 时,您会看到“看来您的反向代理设置已损坏”错误。
proxy_pass http://localhost:8080/;
Remove this -----------------------------^
应该读作
proxy_pass http://localhost:8080;