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

相关文章:

  1. Nginx的if
  2. HTTP keep-alive
  3. Ubuntu切换国内镜像(通用版)
  4. 查看Linux发行版
  5. 抓取指定时间区间的日志
  6. Windows7 安装 IE10
  7. 昨天发现的,然后在application.yml中配置“hibernate.dialect.storage_engine=innodb”。但是自动生成的表还是不会设置为innoDB,看了底层源码。这个配置也是没有加载到的 原来是要在hibernate.properties中加这个配置。感谢 2019-06-22 我也发现了这个注释:注释“Use "hibernate.dialect.storage_engine=innodb" environment variable or JVM system property instead.” ----- 坑啊。。。。。。。 2019-03-02