Nginx rewrite规则无匹配优先级,真正决定请求处理的是location块的匹配顺序:先精确匹配(=),再长前缀(^~),然后按序扫描正则(~或~*),最后是最长普通前缀;rewrite仅在匹配的location内按书写顺序执行,last触发重新匹配,break终止当前location内后续rewrite。

Nginx 的 rewrite 规则本身不参与“匹配优先级”的排序,真正决定请求如何被处理的是 location 块的匹配顺序,而 rewrite 指令只是在 location 内部执行的重写逻辑。换句话说:rewrite 不抢 location 的风头,它只听 location 的安排。
所以问题的核心其实是:请求先落到哪个 location,然后才轮到里面的 rewrite 执行。搞清 location 匹配规则,就等于理清了 rewrite 实际生效的上下文。
location 匹配优先级是关键
Nginx 严格按以下顺序查找匹配的 location: - 精确匹配(=)最高优先,命中即停 - 长前缀匹配(^~)次之,只要最长且带 ^~ 就立即结束搜索 - 正则匹配(~ 或 ~*)按配置文件中出现的**先后顺序**扫描,**第一个匹配成功即用** - 普通前缀匹配(无修饰符)取**最长前缀**,但会被上面三类打断举个例子:
location = /api { ... } # 精确匹配 /api,优先级最高<br>location ^~ /api/ { ... } # /api/ 开头的请求走这里,不看正则<br>location ~ ^/api/\d+$ { ... } # 正则,仅当没被上面拦截时才轮到它<br>location /api/ { ... } # 普通前缀,只有前面都没匹配上才考虑rewrite 在 location 内的执行时机
rewrite 指令在 location 块内按**书写顺序依次执行**,每条 rewrite 都可能改变 URI,后续 rewrite 作用在新 URI 上。 如果某条 rewrite 带 last 标志,Nginx 会重新开始 location 匹配(相当于内部跳转); 用 break 则终止当前 location 内所有 rewrite,不再重匹配; redirect 和 permanent 是 302/301 返回,不继续执行后续 rewrite。常见写法示例:
-
rewrite ^/old/(.*)$ /new/$1 last;→ 改写后重新找 location -
rewrite ^/static/(.*)$ /assets/$1 break;→ 改写后直接用当前 location 处理 -
rewrite ^/login$ /auth/login permanent;→ 301 跳转,客户端重发请求
容易踩坑的点
- rewrite 的正则默认区分大小写(~),不区分要用 ~* - URI 在进入 rewrite 前已被解码,但 $1、$2 捕获的是原始编码内容(比如 %20 还是 %20,不是空格) - 使用 last 时注意循环风险:若新 URI 又命中同一 location,可能无限重写(Nginx 会报 500 错误并终止) - rewrite 不影响变量 $request_uri(始终是原始请求 URI),但 $uri 是重写后的路径(可用于日志或条件判断)调试建议
开启 rewrite 日志可直观看到执行过程:rewrite_log on;<br>error_log /var/log/nginx/rewrite.log notice;注意:rewrite_log 默认关闭,且只在 notice 级别及以上输出,需配合 error_log 使用。
不复杂但容易忽略——rewrite 本身没优先级,它只是 location 的“手下”,location 才是调度中心。


















