Skip to content

Nginx 进阶:一次性带你彻底搞懂玄学的 Location 匹配规则

毛佳国

很多个人开发者在使用 Nginx 的时候,面对配置文件中最多的 location 块,大多数情况靠的是“复制粘贴大法”。 在从网络上抄来的配置里,你会看到无数个长得非常类似但又有着微妙符号区别的代码段: 有的是 location = /,有的是 location ~ \.php$,还有的干干脆脆就是一个 location /

直到有一天,你要配置一个前后端分离的项目。前台的静态资源希望走普通的静态文件代理,而所有带有 /api/ 的接口请求必须转发给后面监听本地端口的 Java 或者是 Node 服务。这时你发现自己抄来的规则突然都不管用了。这其实是因为 Nginx 在面对 URL 进行路由分发时,内嵌了一套极度反直觉但是又异常精确的“选妃”优先级规则

在 2024 年,别再瞎试符号了。

Nginx 的匹配核心:从四种符号开始

Nginx 在 server 块接收到了一个用户的 HTTP 请求(比如:https://example.com/api/v1/user),它会抽出后面的 URI 路径(/api/v1/user),然后按照以下四个主要符号匹配规则去逐个对号入座。

第一等公民:精准全等匹配 (=

这和代码里的判断完全一致。

location = /login {
    # 只要你的路径精确地等于 /login
    # 多一个斜杠,多一个参数,都不行!
}

优先级:史上最高。一旦它命中,Nginx 立刻停止搜寻后面的任何规则。

第二等公民:长前缀特权匹配 (^~

这就是这套规则里最玄学和容易误导人的符号(带个 ~ 但人家根本不是正则!)。

location ^~ /api/ {
    # 只要你访问的是以 /api/ 开头的(比如 /api/v1, /api/auth...)
}

优先级:一旦有以它开头的匹配,停止寻找后面的正则

第三等公民:正则表达式匹配(~ 大小写敏感 / ~* 大小写不敏感)

在所有的正则前缀里,~ 区分了 URL 的大小写,而加上星号 ~* 就忽略大小写了。

location ~* \.(jpg|jpeg|png)$ {
    # 所有以这几个图片结尾的,哪怕你写成了 .PNG 一样命中
}

优先级:所有正则的匹配,会按照你配置文件里书写的上下顺序进行。排在越上面的,越早被选中。

卑微的平民:普通前缀字符串匹配(啥都不带)

location / {
    # 万金油,只要是 / 开头(也就是所有请求)都会被捕捉到
}

优先级:最低层级。它是备胎中的备胎,别人都匹配不上的时候,才会轮到它出来兜底。

Nginx 选妃的终极顺口溜!

千万别去死记硬背枯燥的表格,记住这段话:

  1. 先在一堆带等号 = 的贵族里找。找到了?直接结束,带走!
  2. 找不到精准等号的,再在一堆 ^~ 和普通字符串(啥都不带的)里找出匹配度最长的那一个。
  3. 找出最长的那个后:如果这个最长的是个带 ^~ 的刺头,那么直接结束,跟刺头走!
  4. 如果最长的是个普通平民(啥也不带的),对不起,先把它当成备胎候补留着。Nginx 还要去翻一翻正则牌子。
  5. 去看下正则 ~~*。按照文件从上到下的顺序,谁第一个能匹配上,就直接跟正则走!
  6. 如果所有的正则都没一个匹配上的,没办法,只能回来牵走刚才的备胎平民。

真题实战:你能说出它走哪个吗?

如果配置文件是这样的:

location /api { ...规则 A }
location ^~ /api/user { ...规则 B }
location ~ /api/v1 { ...规则 C }
location = /api/v1 { ...规则 D }

用户访问了 http://domian.com/api/v1

如果你把这个优先级牢记心中,下一次调反向代理的坑,你一眼就能看出哪里截胡了,真正体会一把庖丁解牛的快感。

上一篇
从 Shadowsocks 到 VLESS:翻墙代理协议的十年演进史
下一篇
极客的第一台云服务器:为什么要买海外 VPS 及如何避坑