IT

Nginx location 匹配优先级详解与常见坑

AI智能摘要

Nginx location 到底谁先匹配?=、^~、正则、普通前缀的优先级顺序,配一个例子讲透匹配过程。再聊三个高频坑:最长前缀被正则覆盖、正则顺序写反、rewrite 和 try_files 造成循环,附排查命令。

先给结论:优先级从高到低

Nginx 的 location 匹配不是“按配置顺序从上到下”,而是按类型分层。记住这条顺序,80% 的困惑就没了:

  • = 精确匹配,命中即返回,最高优先级
  • ^~ 前缀匹配,命中后不再检查正则
  • ~ 和 ~* 正则匹配,按配置中出现的顺序,第一个命中的生效
  • 普通前缀匹配(无修饰符),取最长匹配

容易忽略的一点:普通前缀匹配命中后,Nginx 还会继续尝试正则;只有 ^~ 和 = 会“截断”后续检查。所以“最长前缀”不一定最终生效,正则可能后来居上。

一个例子看清匹配过程

假设配置如下:

location = /api { return 200 "exact"; }
location ^~ /static/ { return 200 "prefix-noregex"; }
location ~ .php$ { return 200 "regex-php"; }
location /images/ { return 200 "prefix-images"; }
location / { return 200 "root"; }

请求 /api 命中精确匹配,直接返回。请求 /static/a.php 命中 ^~,即使后面有 ~ .php$ 也不会再检查。请求 /images/x.php 先记住最长前缀 /images/,但随后正则 ~ .php$ 命中,最终走正则。请求 /images/a.png 正则不命中,回落到前缀 /images/。

常见坑一:以为写了最长前缀就一定生效

这是最常见的误解。只要存在能匹配上的正则 location,普通前缀就会被覆盖。解决办法有两个:一是给前缀加 ^~,二是把正则写得更精确。排查时可以用 nginx -T 看完整配置,确认没有隐藏的正则规则(比如 include 进来的通用 ~ .(js|css)$)。

常见坑二:正则顺序与嵌套 location

正则按配置文件中的书写顺序匹配,第一个命中就停,不是“最精确优先”。所以把更具体的正则写在前面,例如先写 ~ ^/api/v2/ 再写 ~ ^/api/。另外,嵌套 location 里的正则只在外层前缀命中后才参与,不要指望外层正则去匹配内层路径。

常见坑三:rewrite 后的 location 与 try_files

在 location 内执行 rewrite ... last; 会重新走一遍 location 匹配,可能落入另一个 location,形成循环时 Nginx 会报 “rewrite or internal redirection cycle”。用 try_files $uri $uri/ /index.html; 做单页应用回退时,要确保最后的回退目标本身不会再触发同一段逻辑,否则同样会循环。调试阶段可在 server 块临时加 error_log /var/log/nginx/debug.log debug;,观察实际命中的 location。

最后提醒:改完配置先 nginx -t 校验,再 nginx -s reload 平滑生效,不要直接 restart 生产环境。

发表评论