Nginx location 优先级详解:匹配规则、修饰符与完整代码示例

Nginx location 优先级详解(附完整示例)

Nginx location 的匹配并非简单地按配置顺序执行,而是一套基于修饰符的优先级规则。其核心优先级顺序为:精确匹配 (=) > 带 ^~ 的最长前缀匹配 > 正则匹配 (~ / ~*,按配置顺序) > 普通最长前缀匹配。

一、location 语法与修饰符

nginx 复制代码
location [修饰符] 匹配模式 { ... }
修饰符 含义 匹配方式
= 精确匹配 URI 与模式完全相等
^~ 前缀匹配(优先) URI 以模式开头,命中后不再检查正则
~ 正则匹配(区分大小写) PCRE 正则
~* 正则匹配(不区分大小写) PCRE 正则
无 普通前缀匹配 URI 以模式开头
@ 命名 location 仅用于内部跳转(try_files、error_page)

二、核心优先级顺序

复制代码
1. =       精确匹配          (最高,命中即返回)
2. ^~      最长前缀匹配       (命中即返回,跳过正则)
3. ~ / ~*  正则匹配           (按配置文件出现顺序,第一个命中即返回)
4. 无修饰符 最长前缀匹配       (记住最长的那个,等正则都失败后才用)
5. /       通用匹配           (兜底)

关键记忆点:

  • = 最优先,命中直接结束。
  • ^~ 命中后短路正则。
  • 正则按书写顺序,不是按路径长短,第一个匹配的正则赢。
  • 普通前缀匹配只是"记住",要等所有正则都失败才回头使用。

三、完整可运行示例

以下配置可直接放入 server {} 块中,用 curl 逐条验证。

nginx 复制代码
server {
    listen 80;
    server_name test.local;

    # ① 精确匹配(最高优先级)
    location = /exact {
        return 200 "1. exact match\n";
    }

    # ② ^~ 前缀匹配(命中后跳过正则)
    location ^~ /static/ {
        return 200 "2. ^~ prefix match: /static/\n";
    }

    # ③ 正则匹配(按书写顺序)
    location ~ \.php$ {
        return 200 "3a. regex (case-sensitive) .php\n";
    }

    location ~* \.(jpg|png|gif)$ {
        return 200 "3b. regex (case-insensitive) image\n";
    }

    # ④ 普通前缀匹配(最长优先,但要等正则失败)
    location /api/ {
        return 200 "4a. plain prefix: /api/\n";
    }

    location /api/v2/ {
        return 200 "4b. plain prefix: /api/v2/ (longer)\n";
    }

    # ⑤ 通用匹配(兜底)
    location / {
        return 200 "5. default /\n";
    }
}

测试结果对照表

请求 URI 命中的规则 原因
/exact ① = /exact 精确匹配最高
/exact/ ⑤ / 精确匹配不匹配,无其他前缀/正则命中
/static/a.jpg ② ^~ /static/ ^~ 命中后跳过 下面的 \.jpg 正则
/static/a.php ② ^~ /static/ 同上,^~ 短路所有正则
/img/a.JPG ③ `~* .(jpg png
/img/a.php ③ ~ \.php$ 正则按顺序,.php 规则写在前面先命中
/api/users ④ = /api/ 正则都不匹配,回退到最长普通前缀
/api/v2/users ④ = /api/v2/ 最长前缀优先
/anything ⑤ / 兜底

注意:上表 /api/users 命中 /api/,/api/v2/users 命中 /api/v2/(更长的前缀胜出)。但两者都要先经过正则检查,只有正则全失败才会用到它们。


四、易错点:正则 vs 普通前缀

很多人误以为 /api/v2/ 比正则更"具体",所以优先。错! 普通前缀永远排在正则之后。

nginx 复制代码
server {
    # 普通前缀
    location /api/ {
        return 200 "prefix /api/\n";
    }

    # 正则:能匹配 /api/xxx.json
    location ~ \.json$ {
        return 200 "regex .json\n";
    }
}
  • 请求 /api/data.json → 命中 正则 (输出 regex .json),而不是 /api/。
  • 请求 /api/data → 正则不匹配 → 回退到 /api/。

如果想锁定前缀不被正则抢走 ,加 ^~:

nginx 复制代码
location ^~ /api/ {
    return 200 "locked prefix\n";
}
# 此时 /api/data.json 也走这里,不会进 ~ \.json$

五、易错点:正则顺序,而非长度

nginx 复制代码
location ~ \.png$ {
    return 200 "A: lowercase png only\n";
}
location ~* \.png$ {
    return 200 "B: case-insensitive png\n";
}
请求 结果 说明
/a.png A 第一个正则就命中(小写 png)
/a.PNG B A 区分大小写失败,落到 B

如果两个都写 ~* 且都能匹配,永远只有第一个生效,第二个是死代码。


六、完整匹配流程图

复制代码
请求 URI
   │
   ▼
[1] 查 = 精确匹配 ──命中──▶ 使用,结束
   │未命中
   ▼
[2] 遍历所有前缀匹配(含 ^~ 和普通),记录"最长前缀"
   │
   ▼
[3] 最长前缀是否为 ^~ ?──是──▶ 使用该 ^~ 规则,结束
   │否
   ▼
[4] 按顺序遍历 ~ / ~* 正则 ──第一个命中──▶ 使用,结束
   │全不命中
   ▼
[5] 使用 [2] 记录的最长普通前缀 ──存在──▶ 使用,结束
   │不存在
   ▼
[6] 使用 location / 兜底

七、常见实战片段

1. 静态资源 + SPA 路由

nginx 复制代码
server {
    root /var/www/dist;

    # 静态资源:^~ 防止被后面的正则或 SPA 兜底抢走
    location ^~ /assets/ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 图片缓存
    location ~* \.(jpg|jpeg|png|gif|webp|svg)$ {
        expires 7d;
    }

    # API 反向代理
    location /api/ {
        proxy_pass http://backend;
    }

    # SPA 兜底(放在最后)
    location / {
        try_files $uri $uri/ /index.html;
    }
}

2. 禁止访问隐藏文件(正则优先于通用前缀)

nginx 复制代码
location ~ /\.(git|env|htaccess) {
    deny all;
}
location / {
    try_files $uri $uri/ =404;
}

3. 精确匹配做健康检查(性能最高)

nginx 复制代码
location = /healthz {
    access_log off;
    return 200 "ok";
}

4. 命名 location 用于内部跳转

nginx 复制代码
location / {
    try_files $uri $uri/ @fallback;
}

location @fallback {
    proxy_pass http://backend;
}

命名 location(@name)不参与 普通 URI 匹配,只能被 try_files、error_page、internal 内部跳转触发。


八、速查总结

场景 正确做法
单一入口(如 /health、/login) location = /health
目录要"锁定",不被正则抢 location ^~ /static/
按扩展名处理 `location ~* .(jpg
多个正则都能匹配 注意书写顺序,第一个胜出
SPA / 兜底 location / 放最后
内部跳转 location @name

一句话记忆:= 绝对优先 → ^~ 锁前缀 → 正则看顺序 → 普通前缀看最长 → / 兜底。

参考:https://www.ecjson.com/article/207.html

相关推荐
程序员-Benothing19 小时前
Linux安全加固指南:账号、权限、服务、审计基线
linux·运维·安全
Mininglamp_271819 小时前
接口调用 vs 屏幕理解:两种 GUI 自动化架构的技术取舍
运维·架构·自动化
爱喝水的鱼丶21 小时前
SAP-ABAP:ECC→S/4HANA ABAP 迁移升级指南——程序改造、语法兼容与性能优化 导语
运维·开发语言·性能优化·sap·abap·经验交流·开发交流
木子欢儿21 小时前
openconnect Linux客户端安装 以及开机自启和登录
linux·运维·服务器
..Dauntless..1 天前
【Linux】文件系统(一)
linux·运维·服务器
天空属于哈夫克31 天前
企业微信API二次开发 赋能私域运营自动化
运维·自动化·企业微信
天远API1 天前
零信任架构实战:基于天远运营商二要素V即时版构建自动化分时租赁出行会员身份一致性审核网关
运维·人工智能·架构·自动化
极光通讯1 天前
液冷服务器对内存和SSD的适配要求:高密度部署下的散热与信号完整性
运维·服务器
2501_937767161 天前
面向设计 / 研发部门:终端文件统一归档 + 服务器定时备份实践
运维·安全
重生之高冷汉堡包1 天前
ChatGPT 如何打造自动化账号:从零搭建到高效运营
运维·chatgpt·自动化