nginx location匹配优先级取决于四步严格规则而非书写顺序:先=完全匹配,再^~最长前缀,接着~或~*自上而下首匹配正则,最后普通前缀最长匹配;通用正则应置底或改用^~+try_files避免干扰,server层rewrite会提前改uri影响匹配。

排查 location 匹配优先级混乱,核心是搞清 Nginx 实际走哪一块,而不是“我以为它该走哪块”。重点不在重写配置,而在验证路径真实命中逻辑。
看请求到底进了哪个 location
最直接有效的方式是用 return 或 add_header 做标记:
- 在每个关键 location 块里加一句
return 200 "in /api block";或add_header X-Location-Hit "/static"; - 发起请求后,检查响应体或响应头,确认实际执行的是哪一个
- 避免用日志(如
error_log notice)代替即时反馈——日志有延迟、易被过滤,且不直观
对照匹配流程树逐层排除
Nginx 不按书写顺序选 location,而是严格走四步判断:
- 有没有
location = /xxx完全相等?有就立刻停,不往后看 - 有没有
location ^~ /yyy?找最长前缀,命中即停,正则完全不参与 - 有没有
location ~ ...或location ~* ...?从上到下扫描,第一个能匹配的就用,后面不管多“准”都跳过 - 以上全没中,才选普通前缀
location /zzz中最长的那个
检查正则顺序和覆盖范围
正则规则最容易“静默吞掉”其他配置:
- 宽泛正则(如
location ~* \.(js|css|png)$)若写在前面,会拦截所有带这些后缀的请求,哪怕路径是/admin/api.js或/static/v2.3.1/app.css - 后面更具体的正则(如
location ~ ^/admin/.*\.js$)永远不执行 - 解决方法:把通用正则尽量放到底部;或改用
^~+try_files处理静态资源,避开正则干扰
注意 server 层 rewrite 对 location 的干扰
server 块里的 rewrite 会先于 location 匹配执行,可能悄悄改掉 URI:
- 比如
rewrite ^/(.*)$ /v1/$1 break;会让原本/health变成/v1/health,导致location = /health失效 - 排查时可在 server 块开头加
add_header X-URI-After-Rewrite "$uri";,对比原始请求路径与实际匹配路径 - 非必要不放在 server 层做 rewrite,优先放到具体 location 内











