nginx location匹配遵循优先级规则而非书写顺序:=(精确)、^~(前缀禁正则)、~/~*(正则)、普通前缀(最长匹配),分两阶段执行,=和^~会短路正则匹配。

nginx的location匹配不是“谁写在前面就用谁”,而是有一套明确的优先级规则。理解这套规则,才能避免配置冲突、路径错配或静态资源404等问题。
location匹配的四类语法及其权重
nginx将location分为四类,按匹配优先级从高到低排列:
-
=(精确匹配):完全一致才命中,优先级最高。例如
location = /api只匹配/api,不匹配/api/或/api/users -
^~(前缀匹配,非正则且禁止正则回溯):以指定字符串开头即匹配,且一旦命中,不再检查任何正则location。适合静态文件目录,如
location ^~ /static/ -
~ 和 ~*(区分/不区分大小写的正则匹配):按配置文件中出现顺序依次尝试,命中即停。其中
~*更常用(如location ~* \.(jpg|png|gif)$) -
普通前缀匹配(无修饰符):最长前缀匹配,优先级最低。例如
location /api和location /api/users同时存在时,请求/api/users/list会匹配后者
匹配流程:先找最优前缀,再看是否触发正则
nginx实际执行两阶段匹配:
- 第一阶段:扫描所有location,找出所有能匹配URI前缀的项(包括=、^~、普通前缀),选出最长前缀匹配项
- 第二阶段:若该最长前缀项是
=或^~,直接采用,跳过所有正则;否则,继续按顺序检查所有~/~*location,取第一个匹配的正则项
注意:=和^~本质是“短路型”匹配——一旦满足,正则根本不会被评估。
常见陷阱与避坑建议
这些细节极易引发线上问题:
- 误以为
location /admin能覆盖location ~ \.php$:实际上,如果请求是/admin/index.php,先匹配最长前缀/admin(普通前缀),再进入正则阶段,最终由~ \.php$接管——PHP处理逻辑生效,但可能绕过预期的/admin权限控制 - 混用
^~和正则导致静态资源无法压缩:比如location ^~ /assets/后又写了location ~* \.js$,后者永远不会执行。应统一用^~或改用location /assets/+ 正则子块 - 忽略尾部斜杠差异:
location /api和location /api/是两个不同前缀;前者匹配/api?x=1,后者匹配/api/user但不匹配/api - 正则location中未锚定开头:写成
location ~ php$会错误匹配/index.php.bak,应写作location ~ \.php$或location ~ ^/app/.*\.php$
调试技巧:快速验证实际匹配结果
不用重启就能确认location是否如预期工作:
- 启用
error_log /path/to/error.log notice;,访问目标URL后查看日志,nginx会在notice级别输出类似"*123456 \"GET /api/v1/users\" matches "^~ /api/", client: 127.0.0.1"的匹配信息 - 用
curl -I http://localhost/xxx配合add_header X-Location-Match "$location"临时添加响应头,在配置中为每个location块加该指令,直观看到哪个块生效 - 使用
nginx -t只能校验语法,不能验证逻辑;真正要确认行为,必须结合日志或响应头实测











