Nginx 反向代理 + URL 重写

jef*_*eon 241 nginx reverse-proxy 301-redirect

Nginx 在端口 80 上运行,我使用它来反向代理 URL,并/foo3200这种方式使用端口路径:

location /foo {
                proxy_pass http://localhost:3200;
                proxy_redirect     off;
                proxy_set_header   Host $host;
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我在 port 上有一个应用程序3200,我不希望将初始/foo值发送到该应用程序。也就是说 - 当我访问时http://localhost/foo/bar,我只想/bar成为应用程序接收到的路径。所以我尝试将此行添加到上面的位置块:

rewrite ^(.*)foo(.*)$ http://localhost:3200/$2 permanent;
Run Code Online (Sandbox Code Playgroud)

这会导致 302 重定向(更改 URL),但我想要 301。我该怎么办?

Jen*_*ler 253

从远程系统(例如客户端的 Web 浏览器)重定向到 localhost 没有任何意义。因此,重写标志永久 (301) 或重定向 (302) 在您的情况下不可用。

请尝试使用透明重写规则进行以下设置:

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}
Run Code Online (Sandbox Code Playgroud)

使用curl -i来测试你的重写。对规则的一个非常微妙的更改可能会导致 nginx 执行重定向。

  • 正则表达式可能应该是`/foo(.*)`,否则将不会匹配`example.com/foo`。(这可能是 jeffreyveon 所经历的) (14认同)
  • 如果您还想匹配不带斜杠的`/foo`:`rewrite /foo(/.*|$) /$1 break;` (7认同)
  • 当我这样做时,我的应用程序中的 URL 路径仍然以 /foo 开头...... (2认同)
  • 使用“break”意味着重写过程停止,更改后的请求将不会被另一个位置处理。如果您使用“last”,重写过程也会停止,但 Nginx 将再次处理更改后的请求以查找匹配的位置指令。 (2认同)

Dan*_*Arl 206

只要您在 proxy_pass 指令中指定一个 URI,简单的位置前缀匹配就可以解决这个问题,而无需使用重写规则:

location /foo {
  proxy_pass http://localhost:3200/;
}
Run Code Online (Sandbox Code Playgroud)

请注意指令/末尾的附加内容proxy_pass。NGINX 将去除匹配的前缀/foo并将剩余部分传递给 URI 处的后端服务器/。因此,http://myserver:80/foo/bar将在http://localhost:3200/bar.

来自proxy_pass 上NGINX 文档

如果 proxy_pass 指令使用 URI 指定,那么当请求传递到服务器时,与位置匹配的规范化请求 URI 部分将被指令中指定的 URI 替换:

  • 比我添加 / 到位置 /foo/ { 更适合我 (19认同)
  • 如果你这样做,这实际上会将 `//xyz` 传递给主机。 (13认同)
  • 花了太长时间才意识到保留或删除尾部斜杠的重要性。 (2认同)

cns*_*nst 98

绝对最正确的方法和最佳实践通常如下:

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}
Run Code Online (Sandbox Code Playgroud)
  • 请注意尾随斜杠proxy_pass的可怕重要性,它会自动更改$uri变量以/foo/使前端的 与/后端对应。不需要明确的rewrite指令。

  • 此外,请注意,在尾随/location是非常重要的,以及-没有它,你就有可能在一个点(例如,工作有您的网站看起来怪怪的网址,/fooen/foo/en)。

    此外,尾随/locationproxy_pass也保证了一些特殊的处理,具体根据的文件location指示,以有效地使一个隐含的location = /foo {return 301 /foo/;}为好。

    因此,通过location像上面那样定义带有尾部斜杠的a ,您不仅可以确保像这样的/fooen无斜杠后缀 URL将无效,而且/foo没有尾部斜杠的 a也将继续工作。


参考文档:

  • 虽然这个解决方案“似乎”在所有这些论坛上都胜出,但应该在答案中注意到 Nginx 将对 URL 进行 URL 解码并将解码后的 URL 传递给代理服务器。因此,如果您的 URL 带有 URL 编码部分,则此解决方案将不起作用。 (7认同)