Skip to content

07 · location 匹配规则 · Nginx 最绕的部分

生活类比:Nginx 的 location机场分诊台 + VIP 优先通道 + 经济舱通道——同一个旅客可能符合好几个通道,但只能走一条。哪条优先?这就是这一章要讲清楚的事。


1. 一图看懂 5 种 location 修饰符

┌──────────────────────────────────────────────────────────────┐
│  =      精确匹配(最高优先级,命中即止)                      │
│  ^~     前缀匹配(命中后不再去测正则)                        │
│  ~      正则匹配(区分大小写)                                │
│  ~*     正则匹配(不区分大小写)                              │
│  无前缀  普通前缀匹配(最长匹配胜出)                         │
└──────────────────────────────────────────────────────────────┘

5 种修饰符的优先级(重要、必背):

①  =                   ← 精确匹配,找到立即用
②  ^~ + 最长前缀         ← 前缀匹配里"最长"的那个
③  ~ / ~*               ← 正则按"配置文件出现顺序"找第一个匹配
④  普通前缀(最长)       ← 正则全没命中,回退到最长前缀
⑤  /                   ← 兜底

一句话记忆:等于优先 → 长前缀阻断正则 → 正则按顺序 → 长前缀兜底 → / 全包


2. 5 种修饰符 · 详细举例

2.1 = 精确匹配

nginx
location = / {
    return 200 'home';
}

location = /favicon.ico {
    access_log off;
    expires 30d;
}

只有 URL 完全等于 / 时才命中。命中之后直接结束所有匹配。

生活类比:你只接待"叫张三"的客户,不接待"张三丰"。

2.2 ^~ 前缀阻断正则

nginx
location ^~ /static/ {
    root /var/www;
    expires 1y;
}

^~ 的特殊点:命中后 不再试正则。即使后面有匹配的正则规则,也不去尝试。

适合:希望某个前缀绝对走这条,避免被正则规则抢走。

2.3 ~ / ~* 正则匹配

nginx
location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
}

location ~* \.(jpg|png|gif)$ {
    expires 1y;
}
修饰符含义
~区分大小写的正则
~*不区分大小写的正则

注意

  1. 正则是按配置文件中出现的顺序找第一个匹配
  2. 第一个匹配上了就用它,后面的正则不再试

2.4 普通前缀(无修饰符)

nginx
location /api/ { ... }
location /api/v2/ { ... }

普通前缀匹配按"最长前缀"原则。/api/v2/foo 会命中 /api/v2/,因为 /api/v2//api/ 长。

但找到后会继续看正则,正则胜出会覆盖前缀匹配(除非用了 ^~)。

2.5 / 兜底

nginx
location / { ... }

所有 URL 都会"匹配上" /,但优先级最低。所以它经常作为兜底,比如 SPA fallback:

nginx
location / {
    try_files $uri $uri/ /index.html;
}

3. 完整匹配流程图

请求来了


┌──────────────────┐
│ 1. 找 = 精确匹配  │ ── 找到 ──► ✅ 用它,结束
└─────────┬────────┘
          │ 没找到

┌──────────────────┐
│ 2. 找最长前缀     │ ── 记下来(暂存)
│   (含 ^~ 和普通) │
└─────────┬────────┘


   暂存的前缀是 ^~ 吗?

        ┌─┴─┐
       是    否
        │    │
        │    ▼
        │   ┌──────────────────┐
        │   │ 3. 顺序找正则     │
        │   │  ~ / ~*          │ ── 命中第一个 ──► ✅ 用它
        │   └─────────┬────────┘
        │             │ 全没命中
        ▼             ▼
        ✅ 用前缀,结束

4. 经典面试题:下面 5 个 URL 各命中哪条?

配置

nginx
server {
    location  = /            { return 200 'A'; }
    location  ^~ /static/    { return 200 'B'; }
    location  ~* \.(png|jpg)$ { return 200 'C'; }
    location  /              { return 200 'D'; }
    location  /api/          { return 200 'E'; }
}

测试

URL答案分析
/A精确匹配 = 命中,结束
/static/logo.pngB^~ /static/ 命中,阻断正则
/img/cat.pngC没命中 ^~,进入正则阶段,命中 ~* \.png$
/api/usersE最长前缀 /api/ 胜过 /,没正则匹配,用 /api/
/aboutD没精确、没 ^~、没正则、最长前缀就是 /

5. 实战:location 的"6 个常用模板"

下面这些可以直接复用到生产配置:

5.1 SPA 兜底

nginx
location / {
    try_files $uri $uri/ /index.html;
}

5.2 静态资源强缓存

nginx
location ~* \.(?:css|js|png|jpg|webp|svg|woff2?)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

5.3 API 反向代理

nginx
location /api/ {
    proxy_pass http://api_backend/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

5.4 健康检查端点

nginx
location = /healthz {
    access_log off;
    return 200 'ok\n';
}

5.5 favicon 单独处理

nginx
location = /favicon.ico {
    access_log off;
    log_not_found off;
    expires 30d;
}

5.6 拒绝隐藏文件

nginx
location ~ /\. {
    deny all;
}

6. try_files 深入 · location 内部的"路径接力"

nginx
location / {
    try_files $uri $uri/ @fallback;
}

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

@name命名 location,只能内部跳转,不会被外部 URL 直接命中。

应用场景:先找静态文件,没有就转到后端动态生成。


7. rewrite vs return vs try_files

指令用法副作用
returnreturn 301 URL;直接结束,浏览器看到 30x
rewriterewrite ^/old$ /new last;内部改 URL,可能再次匹配 location
try_filestry_files $uri /index.html;找文件 → 没了就 fallback

3 个常用 rewrite

nginx
# 1. 301 永久跳转
return 301 https://$host$request_uri;

# 2. 去掉尾部斜杠
rewrite ^/(.*)/$ /$1 permanent;

# 3. URL 重写(不改浏览器地址栏)
rewrite ^/blog/(\d+)$ /article.php?id=$1 last;

last vs break

  • last:重写后重新走一遍 location 匹配
  • break:重写后留在当前 location 继续执行

这是 Nginx 第二大让人秃头的点 ⚠️。新人记忆:90% 用 last,没毛病


8. ⚠️ location 匹配 8 大坑

  1. 同时写了 /api//api → 两者都匹配 /api,但 /api/ 不匹配 /api。容易把流量分错。
  2. 加了 ^~ 没生效 → 写成 ~^ 了,反了。^~ 是"前缀阻断",~^ 是"以...开头的正则"。
  3. 正则顺序写错 → 越具体的正则越要写在前面,否则被通配的吃掉。
  4. location 嵌套 → Nginx 允许内嵌但容易出 bug,强烈建议别嵌套
  5. alias 末尾斜杠location /a/alias /var/www/b/ —— /a/ 末尾必有斜杠对应。
  6. 正则带变量location ~ /api/$arg_v/ 写法不合法;变量在 location 上不起作用。
  7. if 在 location 里 → 官方 wiki 标题 "If is evil"——除了 returnrewrite 几乎啥都不能写。能用 try_files / map 解决就别用 if
  8. try_files 多个文件名都不存在 → 需要兜底参数(最后一个),否则报错。try_files $uri $uri/ =404... /index.html

9. 章末面试题速览

详见 qa.md 第 20-22 题。

  1. Nginx location 5 种修饰符的优先级是?= > ^~ +最长前缀 > ~ / ~*(顺序) > 普通前缀(最长)。
  2. ^~~ 区别?^~ 是前缀且阻断正则;~ 是正则匹配。
  3. if 为啥被官方说 "evil"? → 行为反直觉、容易死循环、嵌套混乱;优先用 try_filesmap 替代。

10. 一句话总结

location 匹配 = 优先级排序 + 修饰符:精确 > 前缀阻断 > 正则按顺序 > 最长前缀 > / 兜底——配合"6 个常用模板",覆盖 95% 的真实场景。

下一章 → 08 · HTTPS 配置:让你的站点带上"小绿锁"。

🎬 可视化演示

下方 demo 给你一份预设的 Nginx 配置,输入任意 URL → 即时高亮"哪条 location 命中",并把整个匹配步骤一步步播给你看。

🎬 可视化演示

演示加载缓慢或样式异常?点此在新标签页打开 ↗