做Nginx配置和运维这些年,rewrite重写功能是我几乎每个项目都会用到、也最常看到新人写错的地方。简单说,Nginx rewrite就是在收到请求之后、发出响应之前,把请求的URI改写成另一个URI,再决定走内部处理流程,还是告诉浏览器去新地址。它解决的核心问题其实就两类:一类是把各种旧链接整理成新结构,另一类是在不改后端代码的情况下,让同一套服务同时兼容老接口和新接口。这篇文章会从语法、执行顺序、location优先级、实际场景和坑点排查这几个维度来聊,适合刚接触Nginx的开发者,也适合配过一段Nginx但一直没把last和break彻底理清的人。看完之后,至少你遇到rewrite相关的404、循环跳转、配置不生效时,能有一个清晰的排查思路。
1. rewrite到底在解决什么问题
1.1 从一次URL迁移说起
我记得有次帮朋友迁移一个个人博客,旧的链接长这样 /index.php?id=123,新程序希望被访问成 /post/123.html。如果只改程序,那收藏夹、搜索引擎里的老链接就全部失效了。这时候可以在Nginx层用一条rewrite规则,把老地址透明地映射到新地址,用户点击旧链接,后端服务收到的是新地址,感知不到中间发生了什么。这种场景就是rewrite最日常的用法:不碰业务代码,只靠反向代理层做URL兼容。
类似的情况还会出现在系统改版、产品改名、文章分类调整、接口版本升级。你会发现,真正需要重写URL的往往不是“想调整一下链接样式”,而是“历史包袱太多,后端已经改名了,但老调用方不能全量通知”。rewrite最大的价值,就是给这些迁移过程留出缓冲期,让老流量平滑过渡到新结构。
1.2 rewrite能做什么,不能做什么
rewrite能做的事情,我归纳了几类:
- URL伪静态:比如把
/index.php?act=show&id=1变成/show/1.html,对搜索引擎更友好。 - 域名级跳转:访问
domain-a.com直接301到domain-b.com,并且保留请求路径。 - 强制定向到HTTPS:判断
$scheme不是https时,整体重写成https地址。 - 规范化URL:统一结尾斜杠、消除多余路径、去掉index.php等。
- 改写请求URI后再转给后端:前端路径和内部后端路径不一致时,rewrite之后配合proxy_pass转发。
但它并不是万能的。rewrite不读数据库、不做业务判断,它只是基于正则表达式对字符串做改写,任何需要依赖Cookie、Session内容做复杂决策的需求,都不适合在这里做。另外,rewrite规则如果堆得太多,会占用worker进程的CPU时间,因为每一层location、每一条规则都要做正则匹配,所以能少写就少写,能放到代码层处理就放到代码层处理。还要区分一个概念:rewrite只是改写URI,如果要直接终止请求、返回某个响应,应该用return,后面我会展开讲。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. rewrite规则的语法与执行机制
2.1 指令格式:rewrite regex replacement [flag]
rewrite的标准语法是:
nginx复制rewrite regex replacement [flag];
一条规则由三部分组成:正则表达式、替换目标URI、可选的标志位。最常见的示例:
nginx复制rewrite ^/article/(\d+)\.html$ /index.php?id=$1 last;
这里 ^/article/(\d+)\.html$ 是正则,用来匹配请求URI;/index.php?id=$1 是替换后的URI,其中 $1 引用正则里第一个括号捕获到的数字;last 是标志位,表示内部继续查找新的location。
三个部分里最容易写错的是正则和替换URI中的转义。比如 \.html 里的点号如果不转义,它会匹配任意字符,导致 /article/123xhtml 这种URL也会被命中。替换目标URI可以写相对路径,也可以写完整的URL。如果写完整的HTTP或HTTPS地址,Nginx会直接给客户端返回3xx跳转,不再内部改写,这一行为很容易被忽略。
2.2 正则匹配的核心规则
Nginx的rewrite正则默认是区分大小写的,不区分大小写需要在开头加 (?i)。常用的正则元字符有:
| 表达式 | 作用 | 示例 |
|---|---|---|
^ |
匹配URI开头 | ^/api 只匹配以/api开头的地址 |
$ |
匹配URI结尾 | \.html$ 只匹配以.html结尾的地址 |
. |
匹配除换行外任意字符 | a.c 可匹配abc、a1c |
* |
前一个字符出现0次或多次 | ab* 可匹配a、ab、abb |
| ` |
