/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。我该怎么办?
#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
)。根据/
指令的文档,带有location
的proxy_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上,您可以选择套接字。这将消除网络堆栈到达本地主机的需要。请谨慎使用此方法,因为主机操作系统上会考虑一些因素。如打开文件数等。
评论
如果您对Grafana机箱有任何问题,则应使用以下配方:docs.grafana.org/installation/behind_proxy/…