Nginx 从Web服务器起步,现在越来越多的承担起反向代理服务器和负载均衡器的角色。
proxy_pass
也就成了很最常用的指令之一,但是
proxy_pass
中,请求URI与传递给后端服务器的URI的转化是很容易弄错的地方,本文通过各种示例展示这个URI的转化规则。
一个简单的例子
假设我们有一个前后分离的应用,前端静态文件存放在
/srv/www/myapp
目录,后端API访问地址是
http://127.0.0.1:8080
。后端提供API接口
/hello
,同时前端访问后端时,统一加
/api
前缀,那这个时候,我们就可以配置为:
现在,就通过
http://127.0.0.1
访问到
/srv/www/myapp
里的静态文件(假设Nginx监听端口80),访问
http://127.0.0.1/api/hello
时,请求都会被转发给
http://127.0.0.1:8080/hello
。
如果我们希望保留
/api/
路径那么只需要把
proxy_pass
配置的URI的path删掉就可以了。
URI的在与不在
URI
在这里不是指完整的URL,而是proxy_pass 指定的URL内服务器地址或端口(如果存在)后面的地址,也就是标准URL定义中的path。
URI = scheme:[//[userinfo@]host[:port]]
path
[?query][#fragment]
proxy_pass http://127.0.0.1:8080/
,URI是
/
;
proxy_pass http://127.0.0.1:8080/api
, URI是
/api
;
proxy_pass http://127.0.0.1:8080
, URI不存在。
请求URI
发起请求的URL内服务器地址或端口(如果存在)后面的地址。例如:
http://127.0.0.1/api/hello
, 请求URI是
/api/hello
。
上游服务器
,被代理服务器,或者说是后端服务器。
指定了URI
1) 如果
proxy_pass
指令
指定了URI
,
请求URI
中匹配location的部分在传递给上游服务器时被
URI
替换掉。
Case 1
请求
http://127.0.0.1/api/hello
, 上游服务器就会收到
http://127.0.0.1:8080/remote/hello
。
(/api/ -> /remote/)
Case 3
请求
http://127.0.0.1/api/hello
, 上游服务器就会收到
http://127.0.0.1:8080/remotehello
。
(/api/ -> /remote)
没有指定URI
2) 如果
proxy_pass
指令
没有指定URI
,那么请求URI就会原样的传递给上游服务器。
请求
/api/hello
, 上游服务器就会收到
/api/hello
。
结尾的
/
location的值是否以
/
结尾,
proxy_pass
的值是否以
/
结尾可以组合出成N多种可能。但是不管怎么组合,只有一个会影响匹配规则:
URI的在与不在
。
location的值最好以
/
结尾。如果location的值如果没有以
/
结尾,例如
/api
,那么URL
/apixxx
也会匹配上。除非明确需要匹配这种
/apixxx
场景。从最小配置的原则上,建议location的值都是以
/
结尾。
proxy_pass的URI,根据项目实际需要赋值或留空。如果有值,那么结尾通常都需要与location的值保持一致--要么都有
/
,要么都没有,不然会拼接出黏连在一起的路径(
/remotehello
)或者出现两个
/
的路径(
/api//hello
)。
更多的Case
Case # Nginx location proxy_pass URL Test URL Path received location /name/ { rewrite /name/([^/]+) /users?name=$1 break; proxy_pass http://127.0.0.1;If 引发的bug
nginx < 1.7.9 有个bug。如果在
location
里使用
if
,会导致
proxy_pass
不按照预期工作。proxy_pass 的
URI
叠加
request_uri
。
就像最开始的例子访问
http://127.0.0.1/api/hello
时,请求都会被转发给
http://127.0.0.1:8080//api/hello
。
相关文章:
- Nginx的if
- HTTP keep-alive
- Ubuntu切换国内镜像(通用版)
- 查看Linux发行版
- 抓取指定时间区间的日志
- Windows7 安装 IE10 昨天发现的,然后在application.yml中配置“hibernate.dialect.storage_engine=innodb”。但是自动生成的表还是不会设置为innoDB,看了底层源码。这个配置也是没有加载到的 原来是要在hibernate.properties中加这个配置。感谢