Nginx 重定向配置详解:return 与 rewrite 的实战指南
重定向是 Web 服务中常见的功能,用于将客户端请求从一个 URL 转发到另一个 URL(如域名迁移、路径调整、HTTPS 强制跳转等)。Nginx 通过return
和rewrite
两种方式实现重定向,各有适用场景。本文详细讲解两种方式的语法、区别及实战案例,帮助灵活配置重定向规则。
重定向基础:状态码与场景
重定向通过 HTTP 状态码告知客户端跳转类型,常用状态码:
- 301 Moved Permanently:永久重定向(客户端会缓存跳转关系,适合域名更换);
- 302 Found:临时重定向(客户端不缓存,适合临时维护、活动页面跳转);
- 307 Temporary Redirect:临时重定向(严格保留请求方法,如 POST 请求不会转为 GET);
- 308 Permanent Redirect:永久重定向(严格保留请求方法)。
return
指令:简单直接的重定向
return
指令用于直接返回状态码和跳转 URL,语法简洁,适合固定规则的重定向(如域名跳转、HTTPS 强制跳转)。
1. 语法格式
1 | # 格式1:仅返回状态码(如404) |
2. 实战示例
HTTP 强制跳转 HTTPS:
1
2
3
4
5
6server {
listen 80;
server_name example.com www.example.com;
# 所有HTTP请求永久重定向到HTTPS
return 301 https://$host$request_uri;
}- 说明:
$host
自动获取请求的域名,$request_uri
保留完整路径和参数(如/api?page=1
)。
- 说明:
域名迁移(旧域名跳新域名):
1
2
3
4
5
6server {
listen 80;
server_name old.example.com;
# 旧域名永久跳转到新域名,保留路径
return 301 https://new.example.com$request_uri;
}路径重定向(单页跳转):
1
2
3
4
5
6
7
8
9server {
listen 80;
server_name example.com;
location /old-page {
# 临时跳转到新页面
return 302 /new-page;
}
}
3. return
的优势
- 执行效率高:一旦匹配
return
,立即终止后续处理,适合作为优先规则; - 语法简单:无需正则表达式,适合固定 URL 跳转;
- 支持变量:可通过 Nginx 变量(如
$host
、$request_uri
)动态生成跳转 URL。
rewrite
指令:基于正则的灵活重定向
rewrite
指令通过正则表达式匹配 URL,并替换为新的 URL,适合复杂规则的重定向(如路径替换、动态参数调整)。
1. 语法格式
1 | rewrite regex replacement [flag]; |
regex
:用于匹配 URL 的正则表达式(如^/old/(.*)$
);replacement
:替换后的 URL(如/new/$1
,$1
表示正则中的第一个分组);flag
:跳转类型(控制重定向后的处理逻辑,可选值见下文)。
2. 常用flag
说明
flag | 作用 | 适用场景 |
---|---|---|
last |
完成当前 rewrite 后,用新 URL 重新匹配所有 location 规则 | 内部路径重写(如/article/123 →/article.php?id=123 ) |
break |
完成当前 rewrite 后,停止后续匹配,继续执行当前 location 内的其他指令 | 代理场景(如配合proxy_pass ) |
redirect |
返回 302 临时重定向,URL 以http:// /https:// 开头时生效 |
临时外部跳转 |
permanent |
返回 301 永久重定向,URL 以http:// /https:// 开头时生效 |
永久外部跳转 |
last和break两者很像,但是使用alias指令时必须使用last,使用proxy_pass时必须使用break,last在本条rewrite执行之后,会对其所在的server{}重新发起请求,而break在本条rewrite执行之后,则会终止匹配
3. 实战示例
路径替换(带参数):
1
2
3
4# 将 /article/123 重写为 /article.php?id=123(内部跳转,地址栏不变)
location / {
rewrite ^/article/(\d+)$ /article.php?id=$1 last;
}- 说明:
(\d+)
匹配数字(如 123),$1
引用该分组,last
表示用新 URL 重新匹配 location。
- 说明:
文件后缀替换:
1
2
3
4# 将 .html 后缀的URL重定向为 .php(外部跳转,地址栏变化)
location / {
rewrite ^/(.*)\.html$ /$1.php permanent;
}- 效果:访问
/page.html
会永久跳转到/page.php
。
- 效果:访问
配合代理的重写:
1
2
3
4
5# 访问 /api/xxx 时,重写为后端的 /v2/xxx 并代理(内部处理,地址栏不变)
location /api/ {
rewrite ^/api/(.*)$ /v2/$1 break; # 使用break避免循环
proxy_pass http://backend;
}- 注意:代理场景必须用
break
,否则last
会导致 Nginx 重新匹配 location,可能引发死循环。
- 注意:代理场景必须用
4. 正则表达式常用语法
rewrite
依赖正则匹配,掌握基础语法是关键:
符号 | 含义 | 示例 |
---|---|---|
^ |
匹配字符串开头 | ^/api 匹配以/api 开头的 URL |
$$` | 匹配字符串结尾 | \.html$$ 匹配以 .html`结尾的 URL |
. |
匹配任意单个字符 | a.b 匹配aab 、acb 等 |
* |
匹配前面字符 0 次或多次 | ab* 匹配a 、ab 、abb 等 |
+ |
匹配前面字符 1 次或多次 | ab+ 匹配ab 、abb 等(不匹配a ) |
? |
匹配前面字符 0 次或 1 次 | ab? 匹配a 、ab |
() |
分组(可通过$1 、$2 引用) |
(a)(b) 中$1=a ,$2=b |
[] |
匹配字符集中的任意一个 | [0-9] 匹配任意数字 |
return
与rewrite
的区别与选择
维度 | return |
rewrite |
---|---|---|
语法复杂度 | 简单(无需正则) | 复杂(依赖正则) |
执行效率 | 高(立即终止处理) | 较低(需正则匹配) |
适用场景 | 固定 URL 跳转(如 HTTPS、域名迁移) | 动态 URL 重写(如路径替换、参数调整) |
灵活性 | 低(仅支持变量拼接) | 高(支持正则分组、条件匹配) |
选择建议:
- 简单跳转(如 HTTPS 强制跳转、域名迁移)优先用
return
; - 复杂规则(如路径正则替换、参数提取)用
rewrite
; - 性能敏感场景(如高并发 API)尽量用
return
,减少正则开销。
高级技巧与注意事项
重定向日志调试:
开启rewrite_log
可记录重写过程,便于排查规则问题:1
2
3
4http {
rewrite_log on; # 开启重写日志(默认记录到error_log,级别notice)
error_log /var/log/nginx/rewrite.log notice; # 单独存储重写日志
}避免循环跳转:
确保重写后的 URL 不会再次被同一规则匹配,例如:1
2
3
4
5# 错误示例:/new 会被重写为 /new/,然后再次匹配规则,导致循环
rewrite ^/(.*)$ /$1/ permanent;
# 正确示例:排除已带斜杠的URL
rewrite ^/(.*[^/])$ /$1/ permanent;
结合
if
条件判断:
对特定条件应用重定向(如特定 User-Agent):1
2
3
4
5
6location / {
# 移动端用户跳转到移动端页面
if ($http_user_agent ~* "Mobile") {
rewrite ^/$ /mobile permanent;
}
}
v1.3.10