我之前写过一篇文章(Nginx location 匹配规则) 介绍过 Nginx 的 location 匹配规则、proxy_pass 路径拼接替换规则。这两类配置逻辑最大的特点就是规则隐晦,但整体知识点集中,逻辑简单。
而今天要讲解的 Nginx 重定向规则,不但有部分隐藏逻辑、内容复杂,而且正则表达式是必备前置知识,整体上更难。笔者当年也花了不少时间才整理清楚。
Nginx 中实现地址重定向、URL 改写跳转,主要依靠两类指令:return 与 rewrite。
一、return 指令
return 仅负责直接返回状态码 + 跳转地址,不会对原始 URL 做复杂的截取和替换,适合简单固定跳转、协议升级、域名迁移、非法请求拦截等场景。
1. return 基础语法
# 格式1:仅返回状态码
return 状态码;
# 格式2:状态码(默认为302) + 跳转URL(常用)
return 状态码 目标URL;
2. 配置示例
return 的语法简单,只需要通过几个示例就能明白。
示例 1:HTTP 强制跳转 HTTPS,永久重定向
location / {
return 301 https://$host$request_uri;
}
示例 2:永久迁移至新域名
server {
listen 80;
server_name old.com;
return 301 https://new.com$request_uri;
}
示例 3:非法路径直接拦截
location ~ /inner {
return 403;
}
3. return 特点
- 优先级高,一旦执行 return,当前请求后续所有 Nginx 配置全部终止;
- 不支持正则截取、路径改写,只能直接跳转或拦截;
- 性能损耗极低,静态跳转场景优先推荐使用 return,不建议滥用 rewrite。
二、rewrite 指令
rewrite 就是 Nginx 的动态 URL 改写工具,能力很强,但是规则也相对复杂。
rewrite 依赖正则表达式匹配请求路径,支持截取分组、路径裁剪、参数拼接、循环改写,专门用来解决复杂场景。
1. rewrite 语法
rewrite 正则匹配规则 替换后的URL [flag标记];
- 匹配规则:支持正则表达式,和 location ~ 正则语法完全一致;
- 替换 URL:支持普通字符串、正则分组捕获(1 2)、Nginx 内置变量;
- flag 标记:控制改写执行逻辑,是 rewrite 最复杂的部分。
2. Flag 标记
匹配和替换逻辑相对明确,flag 标记则是 rewrite 容易踩坑的地方,不同标记决定改写后请求的走向:
- 无标记:顺序执行当前 location 中的全部 rewrite,然后重新发起一轮全局 location 匹配;
- last:立即结束当前 location 后续逻辑,重新发起一轮全局 location 匹配,继续处理改写后的新 URL;
- break:改写 URL 后,不再重新匹配 location,直接使用改写后的 URL 执行当前 location 的后续逻辑;
- redirect:请求立即结束,返回 302 临时重定向;
- permanent:请求立即结束,返回 301 永久重定向,浏览器缓存跳转规则。
对于浏览器的感受来说:
- 无标记、last 和 break 为服务端内部改写路径,浏览器地址栏不变。
- redirect / permanent:由浏览器参与跳转,地址栏发生变化,属于外部显性跳转;浏览器会发起一次额外请求访问重定向后的资源,性能上不如 last / break。
3. 配置示例
示例 1:伪静态改写(动态 URL 转静态地址)
将 /detail?id=123 改写为 /detail/123.html
rewrite ^/detail/(\d+)\.html$ /detail?id=$1 break;
示例 2:临时页面跳转
rewrite ^/about$ /about-us redirect;
示例 3:rewrite 多次执行(无标记)
location /test {
rewrite ^/test/a /1;
rewrite ^/1 /2;
}
无标记执行流程:
- 第一条 rewrite 改成 /1
- 不会立刻跳转,继续往下执行
- 第二条 rewrite 继续匹配,改成 /2
- 全部执行完毕后,用新 URL 重新全局匹配 location
示例 4:添加 last 标记
location /test {
rewrite ^/test/a /1 last;
rewrite ^/1 /2;
}
last 标记执行流程:
- 匹配命中,改成 /1
- 遇到 last:立即终止当前 location 所有逻辑
- 后续
rewrite ^/1 /2不会执行立刻 - 用新 URL 重新全局匹配 location
4. 防止死循环
- 无标记 / last 模式下,会触发重新查找 location;Nginx 为防止 rewrite 死循环,内置全局计数器,每触发一次"重新查找 location」",计数器自增 1。
- 最多仅允许 10 次内部 rewrite 操作,超出限制直接返回 500 错误。