Nginx在端口80上运行,我正在使用它通过以下方式将路径为/foo的代理URL反向转换为端口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/ permanent;


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

评论

如果您对Grafana机箱有任何问题,则应使用以下配方:docs.grafana.org/installation/behind_proxy/…

#1 楼

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

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

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


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

评论


当我这样做时,URL路径仍然在我的应用程序中以/ foo开头...

– jeffreyveon
2012年4月16日在1:48

肯定有另一个问题。几分钟前,我成功重现了此方案。原始网址:http:// development / foo / testme / 1234-在作为代理后端连接的Apache上运行的PHP脚本的REQUEST_URI:'/ testme / 1234'

–詹斯·布拉德勒
2012年4月17日在8:32



正则表达式可能应该是/foo(.*),否则example.com/foo将不匹配。 (这可能是jeffreyveon经历的)

–本诺
2014年1月30日在2:11



这种工作方式,但是我正在使用proxy_set_body设置的主体被删除。

–贾斯汀·托马斯(Justin Thomas)
17年3月23日17:00

重写/(.*)/socket.io/ break;为SOCKET.IO保存我的一天

–user956584
17年7月25日在18:52

#2 楼

只要您在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文档:


如果proxy_pass指令是使用URI指定的,则何时一个
请求传递到服务器,与位置匹配的规范化请求URI
的部分被伪指令中指定的URI代替:


评论


对我有效,比我在/ foo / {

– Andrei N
15年11月26日在10:41

在此可行的同时,另一个答案是更多自我记录。感觉就像魔术。

–埃里克
16年6月6日在19:21

@Eric IMO的性能优势远远超过了可读性方面的缺点。这将更快得多,因为它是简单的替换,而不是调用完整的正则表达式引擎。

– strugee
17年1月26日在21:05

花了太长时间才意识到保持或消除斜杠的重要性。

– Parvez
17年8月2日在9:25

如果这样做,这实际上会将// xyz传递给主机。

–Archimedes Trajano
18 Mar 6 '18 at 16:35

#3 楼

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

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





请注意,proxy_pass中的尾部斜杠极为重要,其中自动更改$uri变量,使前端的/foo/与后端的/相对应。
不需要显式的rewrite指令。

此外,请注意,后面的/ location也非常重要-如果没有它,您可能会冒一点在网站上拥有看起来怪异的URL(例如,除了/fooen之外,还有一个有效的/foo/en)。根据/指令的文档,带有locationproxy_pass还确保了某些特殊处理,从而也有效地导致了隐式location。不仅要确保像location = /foo {return 301 /foo/;}这样的无斜杠后缀URL无效,b另外,没有斜杠的location也将继续工作。



参考文档:


http:/ /nginx.org/r/location
http://nginx.org/r/proxy_pass


评论


好像$ args丢失了:http:// frontend / foo?bar = baz将被代理到http:// backend /。请注意,args不是url的一部分

–万安
17年11月1日17:47



@Vanuan,你确定吗?我敢肯定,如果您使用上面的代码,$ args应该仍然可以正确处理,因为它们与$ uri分开,并且应该重新组装,除非您在proxy_pass中使用显式变量。

–cnst
17年3月3日在6:53

@cnst哦,我明白了。我正在使用主机变量。这与直觉相反。

–万安
17年11月4日在18:08

@ArchimedesTrajano,您不正确,因为对/ foo进行了特殊处理以重定向到/ foo /,因此,除非您在后端做一些奇怪的事情,甚至/ foo请求都仍然可以与上述代码一起使用。 (BTW实际上已经是答案的一部分。)

–cnst
18 Mar 7 '18 at 17:20

尽管此解决方案“似乎”在所有这些论坛上都取得了成功,但应在答案本身中指出Nginx将对URL进行URL解码,并将解码后的URL传递给代理服务器。因此,如果您的URL包含URL编码的部分,则此解决方案将不起作用。

–编码
18年5月8日在22:15

#4 楼

尝试

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




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


评论


如果您给出解释为什么必须像上面这样配置,那么这个答案将是很好的。

– Masegaloeh
15年1月21日在22:36

如果这样做,这实际上会将// xyz传递给主机。

–Archimedes Trajano
18 Mar 6 '18 at 16:35

#5 楼

@Terabuck对不起,您还没有回复。

您不应该使用localhost,因为您依赖于应用程序在带有主机文件的服务器上运行的事实。本地主机只是默认转换为127.0.0.1。没有说明您必须拥有此主机文件。拥有一个很常见。

再次具有环回接口是另一个要依靠的常识,但是您仍然依赖于网络堆栈上的环回接口。没有这两种情况很少见。如果您对此担心。至少在unix / linux上,您可以选择套接字。这将消除网络堆栈到达本地主机的需要。请谨慎使用此方法,因为主机操作系统上会考虑一些因素。如打开文件数等。