IT

Nginx location 匹配优先级详解:搞懂顺序少踩坑

AI智能摘要

Nginx location 匹配顺序经常把人绕晕:=、^~、~、~* 和普通前缀到底谁先谁后?本文用一张配置示例讲清优先级,并总结正则顺序、^~ 与 = 混用、try_files 重定向等常见坑,最后给出排查命中的实用方法。

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 名称。

记住优先级口诀:等号最优先,尖号次之,正则按序,前缀兜底。写配置时把精确规则放最前,正则按具体程度排序,普通前缀只做兜底,基本就不会踩坑。

发表评论