= 优先级最高,仅当URI完全等于指定字符串(不含query string)时立即终止匹配;^~ 在最长前缀匹配成功时跳过正则;正则仅在无更高优前缀时按序执行。

Nginx 的 location 匹配不是“谁写在前面就用谁”,而是有严格优先级规则的。搞不清 =、^~ 和正则(~ / ~*)之间的关系,配置看似生效,实际请求总进错块——尤其是带参数、嵌套路径或重写后二次匹配的复杂业务场景。
什么时候 = 会赢过所有其他匹配?
= 是精确匹配,仅当请求 URI **完全等于**该字符串(不含 query string)时触发,且一旦命中就立即终止匹配、不往下看任何其他 location。它优先级最高,但非常苛刻。
- 例如
location = /api只匹配 恰好是/api的请求,/api/、/api/v1、/api?x=1全都不匹配 - 它不处理尾部斜杠自动归一化,也不关心大小写(除非加
=后跟~*,但那就不是=了) - 常见误用:把
location = /当作“根路径兜底”,结果静态资源如/favicon.ico反而被绕过——因为= /只匹配/,不匹配任何子路径
^~ 不是“非正则”,而是“前缀匹配胜出开关”
^~ 表示:如果这个前缀匹配成功,且比当前已找到的所有前缀更长,Nginx 就直接采用它,**跳过所有正则匹配块**(哪怕后面有更“合适”的 ~)。它本质是性能优化 + 确定性控制手段。
-
location ^~ /static/匹配/static/css/app.css,也匹配/static/,但不匹配/static(缺尾部斜杠) - 它的优先级低于
=,但高于所有正则和普通前缀(/、/api这类无修饰符的) - 容易踩坑:把它和
~混用在同一层级,比如先写^~ /img,再写~ \.png$,后者根本不会被执行——即使请求是/xxx.png,只要 URI 以/img开头,^~就截断了
正则匹配(~ / ~*)只在“没有更高优前缀”时才入场
所有正则 location 都是惰性执行的:Nginx 先扫一遍所有前缀匹配(包括 =、^~、普通前缀),选出最长的那个;只有当这个最长前缀 **不是 = 也不是 ^~** 时,才会回头遍历正则块,按配置顺序逐个尝试,第一个匹配成功的即生效。
-
~区分大小写,~*不区分;两者优先级相同,只看顺序 - 正则里的
$匹配的是整个 URI(不含 query string),所以~ \.js$能匹配/a/b/c.js,但不能匹配/a/b/c.js?v=1—— 因为$锚定的是c.js结尾,query string 不参与匹配 - 若你真需要匹配带参数的路径逻辑,得靠
if ($args ~ ...)或map,而不是指望location正则吃掉 query string
真实业务中必须检查的三个隐性干扰点
很多线上问题不是匹配逻辑错了,而是被其他机制覆盖或干扰:
-
alias和root在location块里行为完全不同:alias /var/www/会把匹配到的路径部分“替换掉”,而root /var/www是“拼接上”;写反会导致 404 或返回错误文件 - 内部重定向(如
rewrite ... last)会触发location重新匹配,此时原始请求的匹配结果作废,新 URI 从头走完整匹配流程——这是嵌套路由、API 网关场景中最容易漏掉的一环 - 如果用了
try_files,它会在当前location内部做文件存在性判断并可能内部跳转,**不触发外部location匹配**,相当于在本块内“短路”了
真正卡住人的从来不是语法记不住,而是你以为匹配结束了,其实 rewrite 或 try_files 已经悄悄启用了另一轮匹配;或者你笃定 ^~ 能挡住正则,却忘了上面还压着一个 = 把请求提前劫走了。











