nginx location匹配优先级为:=(精确匹配)> ^~(前缀匹配且不回退)> ~或~*(正则匹配,按配置顺序)> 无修饰符前缀匹配;同一请求仅进入最高优先级中第一个成功匹配的块。

Location 指令的匹配优先级怎么判断
Nginx 的 location 不是按配置顺序执行,而是按匹配规则的优先级来选——这点最容易被误读。你写在文件底部的 location /api/,可能根本不会生效,如果上面有更精确的前缀匹配或正则匹配抢了先。
优先级从高到低是:=(精确匹配) > ^~(前缀匹配且不继续正则) > ~ 或 ~*(区分/不区分大小写的正则) > 普通前缀匹配(如 location /static/)。
- 用
= /匹配根路径时,它会直接终止查找,连后续所有location都不看 -
^~ /assets/一旦命中,就不会再检查任何正则location ~ \.js$,哪怕路径也符合 - 正则匹配按配置出现顺序执行,第一个成功就用,后面的同级正则不再尝试
如何安全地代理 API 路径(比如 /api/v1/ → 后端)
常见错误是直接写 location /api/ { proxy_pass http://backend; },结果后端收到的请求路径变成 /api/v1/users,而它只期望 /v1/users —— 这是因为 proxy_pass 末尾没加 /,Nginx 默认原样转发整个 URI。
正确做法是让 Nginx 剪掉前缀:
location /api/ {
proxy_pass http://127.0.0.1:8000/;
}
- 注意
proxy_pass后的/:它触发“路径重写”,/api/xxx→/xxx - 如果后端需要保留
/api前缀,就别加末尾斜杠,但得确认后端能处理 - 避免用
rewrite手动剪路径,容易和proxy_pass冲突,优先靠/控制
正则 location 中的变量和转义怎么写才不翻车
正则匹配里,$1、$2 是捕获组,但它们只在当前 location 块内有效;跨块引用会失效。另外,点号 .、问号 ?、加号 + 这些字符必须转义,否则会被当正则元字符解析。
典型场景:匹配 /files/report-2024.pdf 并限制只允许 PDF:
location ~ ^/files/report-[0-9]+\.(pdf)$ {
root /var/www/static;
try_files $uri =404;
}
-
~表示区分大小写,~*更常用(比如匹配.PDF或.Pdf) -
[0-9]+要写成[0-9]\+吗?不用 —— 在location ~里,Nginx 使用 PCRE,+本身就是量词,无需额外转义 - 但
.必须写成\.,否则会匹配任意字符 - 不要在正则里用
$request_uri做判断,它包含 query string,而location只匹配 path 部分
为什么 location /admin/ 和 location /admin 都配了,却总进错块
因为 /admin 是普通前缀匹配,它会匹配 /admin、/admin/、/admin/foo,甚至 /administrator —— 只要开头是 /admin 就算。而 /admin/ 也会匹配 /admin/ 和 /admin/foo,但不匹配 /admin(无结尾斜杠)。
所以两者共存时,/admin 实际上覆盖了所有以它开头的路径,除非你用 = /admin 或 ^~ /admin/ 显式压制。
- 想严格限定目录访问,优先用
location ^~ /admin/+index index.html - 想单独拦截根级
/admin(不带斜杠),必须写= /admin,否则它会被/admin/或更宽泛的前缀吞掉 - 测试时用
curl -I http://localhost/admin和curl -I http://localhost/admin/分别看响应头里的Server或自定义 header,比猜靠谱
location 看似简单,但路径截断、正则作用域、优先级隐含规则这三块,几乎每个都藏了一个重启后才发现的坑。改完务必用 nginx -t 检查语法,再用真实请求路径验证,别只信配置顺序。











