题 Nginx反向代理+ URL重写


Nginx正在端口80上运行,我正在使用它来反转带路径的代理URL /foo 到港口 3200 这条路:

location /foo {
                proxy_pass http://localhost:3200;
                proxy_redirect     off;
                proxy_set_header   Host $host;
}

这工作正常,但我在端口上有一个应用程序 3200,我不想要初始 /foo 被送到。那是 - 当我访问时 http://localhost/foo/bar,我只想要 /bar 成为应用程序收到的路径。所以我尝试将此行添加到上面的位置块:

rewrite ^(.*)foo(.*)$ http://localhost:3200/$2 permanent;

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


95
2018-04-15 17:31




如果你对Grafana案有任何疑问,你应该使用这些食谱: docs.grafana.org/installation/behind_proxy/... - mohsen saeedi


答案:


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

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

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

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


117
2018-04-15 17:56



当我这样做时,URL路径仍以我的应用程序中的/ foo开头... - jeffreyveon
必定存在不同的问题。几分钟前我成功地重现了这个场景。原始网址: HTTP://开发/富/ TESTME / 1234  - 在作为代理后端连接的Apache上运行的PHP脚本的REQUEST_URI:'/ testme / 1234' - Jens Bradler
正则表达式应该是 /foo(.*), 除此以外 example.com/foo 不会匹配。 (这可能是jeffreyveon所经历的) - Benno
这种作品,但我正在设置proxy_set_body的我的身体正在被删除。 - Justin Thomas
重写/(.*)/socket.io/ break;为SOCKET.IO节省我的一天 - user956584


只要在proxy_pass指令中指定URI,简单的位置前缀匹配就可以在不使用重写规则的情况下工作:

location /foo {
  proxy_pass http://localhost:3200/;
}

注意附加 / 在结束时 proxy_pass 指示。 NGINX将剥离匹配的前缀 /foo 并将余数传递给URI的后端服务器 /。因此, http://myserver:80/foo/bar 将发布到后端 http://localhost:3200/bar

来自 关于proxy_pass的NGINX文档

如果使用URI指定proxy_pass指令,那么当a。时   请求被传递给服务器,这是规范化请求URI的一部分   匹配该位置将替换为指令中指定的URI:


86
2017-09-29 03:30



比我添加到/ location / foo / {对我有用 - Andrei N
这正是我所寻找的! - anbiniyar
这是一个非常干净的解决方案,我更希望这是这个问题的规范答案。 - ralien
花了太长时间才意识到保持或删除尾部斜线的重要性。 - Parvez
这实际上会通过 //xyz 如果你那样做主持人。 - Archimedes Trajano


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

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}

  • 注意到的重要性 尾随斜线 proxy_pass,它会自动改变 $uri 变量有 /foo/ 在前端对应 / 在后端。 不需要明确的 rewrite 指示。

  • 另外,请注意 尾随 / 在里面 location 同样非常重要 - 如果没有它,您可能会在某个时刻在您的网站上看到看起来很奇怪的网址(例如,工作正常) /fooen 此外 /foo/en)。

    另外,尾随 / 在里面 location 同 proxy_pass 也确保一些 特殊处理,根据文件 location 指令,有效地导致隐含 location = /foo {return 301 /foo/;} 同样。

    所以,通过定义一个 location 使用上面的尾部斜杠,您不仅可以确保无斜线后缀URL /fooen 不会有效,但也是一个 /foo 没有尾随斜线也将继续工作。


参考文件:


30
2017-08-26 21:12



这是这里最好的答案! - Mo Friedrich
看起来像 $args 丢了: http://frontend/foo?bar=baz 将被代理 http://backend/。请注意,args不是url的一部分 - Vanuan
@Vanuan,你确定吗?我很确定 $args 如果您使用上面的代码,仍应妥善处理,因为它们是分开的 $uri,并且应该重新组装,除非你在你的使用中使用显式变量 proxy_pass。 - cnst
@ArchimedesTrajano,你是不对的,因为有特殊处理 /foo 重定向到 /foo/所以,除非你在后端做一些奇怪的事,甚至 /foo 请求仍然可以使用上面的代码。 (这实际上已经是答案的一部分,BTW。) - cnst
这是最好的答案!这必须向上移动。 - phegde


尝试

location /foo {
    proxy_pass http://localhost:3200/;
    ....

要么

location ^~ /foo {
    proxy_pass http://localhost:3200/;
    ....

0
2018-01-21 16:20



如果您解释为什么必须像上面那样配置,这个答案会很好。 - masegaloeh
这实际上会通过 //xyz 如果你那样做主持人。 - Archimedes Trajano