location 的匹配顺序不是从上往下读那么简单。Nginx 先按类型分组,再按规则比较。记住一句话:精确匹配(=)优先级最高,其次是前缀匹配中最长的,然后是正则匹配(按文件里出现的顺序),最后才是普通前缀匹配。但正则一旦命中就会立即停止后续匹配,这个特性最容易让人踩坑。
一、匹配优先级从高到低
Nginx 官方给出的顺序是:
=精确匹配:完全相等才命中,命中后立即结束。^~前缀匹配:命中后不再尝试正则。~正则匹配(区分大小写)、~*正则匹配(不区分大小写):按配置文件中的先后顺序逐个尝试,命中即停。- 普通前缀匹配:没有修饰符的 location,记录最长匹配结果,但会继续尝试正则。
注意:普通前缀匹配即使匹配到了,也不会立刻返回,Nginx 会继续找正则;只有正则都没命中,才回退到最长的普通前缀匹配。
二、一个例子看懂顺序
server {
listen 80;
server_name example.com;
location = / {
return 200 "exact rootn";
}
location ^~ /static/ {
return 200 "staticn";
}
location ~ .php$ {
return 200 "phpn";
}
location /images/ {
return 200 "imagesn";
}
location / {
return 200 "defaultn";
}
}
访问结果:
/→ 命中= /,返回 exact root。/static/a.png→ 命中^~ /static/,返回 static,不再看正则。/a.php→ 普通前缀/先被记住,随后正则.php$命中,返回 php。/images/a.png→ 普通前缀/images/最长,但正则没命中,回退返回 images。/other→ 普通前缀/,返回 default。
三、常见坑:正则顺序与嵌套
坑 1:正则顺序决定结果。 ~ .php$ 写在 ~ .php.* 前面,后者可能永远不生效。正则 location 按文件出现顺序匹配,先命中先返回。
坑 2:^~ 不是“优先于 =”。 精确匹配 = 始终最高。如果同时写 = /static/a.png 和 ^~ /static/,前者优先。
坑 3:嵌套 location 的匹配范围。 嵌套 location 只会在父 location 命中后,在父块内部继续匹配,不会跨出父级范围。父级用 ^~ 时,子级正则仍可在父块内生效,但不会影响外部。
坑 4:try_files 与正则的配合。 如果 location / 里用 try_files $uri $uri/ /index.php;,而 /index.php 又被正则 ~ .php$ 捕获,最终会走 PHP 处理,这是常见 SPA 伪静态写法,但要注意 try_files 的最后一个参数是内部重定向,会重新走一遍 location 匹配。
四、排查建议
遇到“为什么没进我写的 location”,按这个顺序查:
- 先确认请求 URI 是否被
=或^~提前截胡。 - 再检查正则 location 的书写顺序,把更具体的正则放前面。
- 用
nginx -T输出完整配置,确认没有 include 进来的隐藏 location。 - 开启 debug 日志:
error_log /var/log/nginx/error.log debug;,日志里会打印实际匹配到的 location 名称。
记住优先级口诀:等号最优先,尖号次之,正则按序,前缀兜底。写配置时把精确规则放最前,正则按具体程度排序,普通前缀只做兜底,基本就不会踩坑。

