跳转到内容

Nginx的location与proxy_pass配置

在使用Nginx做反向代理时,常用locationproxy_pass进行配置。例如:

nginx.conf
http {
server {
location /proxy {
proxy_pass http://localhost:9000 ;
}
}
}

假设Nginx运行在localhost:8080上,那么当访问http://localhost:8080/proxy时,实际访问的是http://localhost:9000上运行的服务。

配置效果表格

不过,更加详细地,访问路径(代理前)与实际路径(代理后)是如何对应的呢?这根据location后面有没有/,以及proxy_pass的IP、端口号后面有没有/或更多内容,实际情况是不一样的。如下表所示:

编号locationproxy_pass访问路径(代理前)实际路径(代理后)
1/proxyhttp://localhost:9000/proxy/service/proxy/service
2/proxyhttp://localhost:9000//proxy/service//service
3/proxyhttp://localhost:9000/app/proxy/service/app/service
4/proxyhttp://localhost:9000/app//proxy/service/app//service
5/proxy/http://localhost:9000/proxy/service/proxy/service
6/proxy/http://localhost:9000//proxy/service/service
7/proxy/http://localhost:9000/app/proxy/service/appservice
8/proxy/http://localhost:9000/app//proxy/service/app/service
9/http://localhost:9000/proxy/service/proxy/service
10/http://localhost:9000//proxy/service/proxy/service
11/http://localhost:9000/app/proxy/service/appproxy/service
12/http://localhost:9000/app//proxy/service/app/proxy/service

根据实际路径的格式正确性,可以认为其中第2、4、7、11种配置是“不应该”的(删除线)。具体应该使用哪一种配置,显然要根据业务场景而定。(我个人更加偏好第5种配置。)

路径处理规律

乍一看情况比较复杂,但实际上有简单的规律可循,只需要区分两种情况

  • 情况Aproxy_pass的URL当中只有IP、端口号,后面什么都没有,就连/都没有。此时,访问的路径将被原封不动地拼接到IP、端口号的后面。(上表中的第1、5、9种配置都是如此。)
  • 情况Bproxy_pass的URL除了IP、端口号之外,后面有一个/或者更多内容。此时,访问的路径将去掉location的前缀部分,并将剩余的路径拼接到proxy_pass的后面。(上表中的第2、3、4、6、7、8、10、11、12种配置都是如此。)

例如上表第1种配置,proxy_passhttp://localhost:9000,后面没有/或更多内容,属于情况A。此时直接拼上访问路径/proxy/service即可得到实际路径http://localhost:9000/proxy/service

又如上表第3种配置,proxy_passhttp://localhost:9000/app,后面多了/app的部分,属于情况B。此时将访问路径/proxy/service的开头裁剪掉location/proxy,只得到剩余的/service部分,将其拼接到proxy_pass后面。即:

Step 1: "/proxy/service" - "/proxy" = "/service"
Step 2: "http://localhost:9000/app" + "/service" = "http://localhost:9000/app/service"

这样就清楚了很多。

本文的location配置没有使用修饰符(location modifier),只是简单的路径前缀匹配而已。相关配置专题请参考另一篇文章(TODO)