Nginx rewrite指令必须置于server或location块内,不可在http顶层使用;常用flag中last触发新location匹配,break留在当前location继续执行,redirect返回302,permanent返回301。

Nginx 的 rewrite 指令用于在请求处理过程中修改 URI,它不改变用户看到的地址(除非用 redirect 或 permanent),而是内部调整路径后交由后续逻辑处理。关键不在“会不会写正则”,而在于位置对不对、flag 选得准不准、匹配逻辑是否和 location 协同。
rewrite 必须放在正确的位置
不能直接写在 http 块顶层,否则 Nginx 启动会报错:"rewrite directive is not allowed here"。必须嵌套在 server 或 location 块中。
- 想改所有以 /old/ 开头的请求 → 放进
location /old/ { ... }里 - 想统一处理 PHP 入口(比如隐藏 .php 后缀)→ 通常放在
location / { ... }中,且要避开已有的location ~ \.php$ - 避免在 if 块里写 rewrite —— 官方明确不推荐,容易引发不可预测行为
四个常用 flag 的实际作用
flag 决定重写后的走向,选错会导致跳转循环、404 或规则静默失效。
-
last:URI 被重写后,Nginx 会丢弃当前 location,用新 URI 重新匹配 location 块。适合路径标准化,比如把
/blog/2024/12改成/index.php?year=2024&month=12,再交给 PHP 处理 -
break:重写后留在当前 location 内继续执行后续指令(如 try_files)。适合简单路径补全,比如把
/static/v2/logo.png改成/static/logo.png,不希望再走一遍 location 匹配 - redirect:返回 302,浏览器地址栏会变,适合测试或临时迁移
- permanent:返回 301,SEO 友好,但上线后改错难回退,慎用
正则写法与常见陷阱
rewrite 使用 PCRE 正则,捕获组用 $1、$2 引用,注意转义和边界。
- 匹配带参数的路径时,regex 只匹配 URI 路径部分(? 后面的 query string 不参与),但 replacement 中可以拼接
$args保留原参数 - 错误示例:
rewrite ^/user/(.*) /profile?id=$1;—— 缺少 flag,Nginx 默认当 last 处理,但若没对应 location,可能 404 - 正确示例:
rewrite ^/user/(.*)$ /profile?id=$1 last;,并确保有location = /profile { ... }或能被location /捕获 - 调试时可开启
rewrite_log on;(需配合 error_log notice),日志会记录每次重写过程
结合 location 实现典型需求
rewrite 不是孤立运行的,它和 location 的匹配顺序密切相关。
- 用户访问
/p/123,想交给index.php?post_id=123→ 在location / { ... }中写:rewrite ^/p/(\d+)$ /index.php?post_id=$1 last; - 强制 www 跳转:
if ($host != 'www.example.com') { rewrite ^(.*)$ https://www.example.com$1 permanent; }(虽然 if 不推荐,但这类域名跳转属常见例外) - 静态资源版本号剥离:
rewrite ^/static/v\d+/(.*)$ /static/$1 break;,配合location /static/块服务文件


















