2026.05.29 | youres | 9次围观
前言
用 Nginx 做重定向,很多人分不清 return 301 和 return 302 在参数处理上到底有什么区别。表面上看只是永久和临时的差异,但实际上两者在查询参数保留、POST请求体处理、浏览器缓存行为上都有细微但关键的差别。本文用实战角度把这些问题讲清楚。
一、301和302的本质区别
先说结论:
- 301:永久重定向,浏览器和搜索引擎会把旧URL的权重转移到新URL
- 302:临时重定向,搜索引擎会继续抓取原URL,不转移权重
从参数处理角度看,301和302在查询参数行为上完全一致——它们都不会自动保留原请求的查询参数,除非你显式在重定向URL里拼接。
二、return 301/302 参数处理的核心问题
最常见的问题:用 return 301 做跳转后,原URL携带的查询参数(如 ?utm_source=xxx)消失了。
原因:return 指令重定向到的是一个你指定的URL,Nginx 不会自动把原请求的查询参数附加到这个URL后面。
# 错误示例:参数会丢失
location /old/ {
return 301 https://www.youres.cn/new/;
}
# 访问 /old/?utm_source=wechat 会跳转到 /new/ (参数没了)
正确写法:手动拼接参数
# 方法1:用 $is_args$args 拼接原参数
location /old/ {
return 301 https://www.youres.cn/new/$is_args$args;
}
# 方法2:用 $request_uri 保留完整原始URI(含参数)
location /old/ {
return 301 https://www.youres.cn$request_uri;
}
三、302临时重定向的参数处理
return 302 在参数处理上与 301 完全相同——都不会自动保留参数,都需要显式拼接。
# 302 同样需要拼接参数
location /temp/ {
return 302 https://www.youres.cn/new/$is_args$args;
}
302 的典型使用场景:临时维护页面、A/B测试流量分发、临时活动页面跳转。
四、POST请求下 301/302 的参数行为
这里有一个很多人忽略的关键点:
301和302重定向,浏览器会自动把POST请求转为GET请求,请求体(body)会丢失。这意味着:
- 原POST请求的参数(在body里)→ 重定向后消失
- 原POST请求的查询参数(在URL里)→ 需要在重定向URL里拼接才能保留
保留POST请求体的正确方案:用307或308
# 307:临时重定向,保留请求方法和请求体
return 307 https://www.youres.cn/new/;
# 308:永久重定向,保留请求方法和请求体
return 308 https://www.youres.cn/new/$is_args$args;
五、$is_args 和 $args 的作用详解
| 变量 | 含义 | 示例 |
|---|---|---|
$is_args | 如果原请求有参数则返回 ?,否则返回空字符串 | 有参数时:?,无参数时:"" |
$args | 完整的查询参数字符串(不含?) | utm_source=wechat&page=2 |
$is_args$args | 拼接后完整参数(含?前缀) | ?utm_source=wechat&page=2 或无后缀 |
正确用法:
return 301 https://www.youres.cn/new/$is_args$args;
# 有参数时跳转:/new/?utm_source=wechat
# 无参数时跳转:/new/ (不会多一个?)
六、实战配置示例
场景1:HTTP跳转HTTPS并保留所有参数
server {
listen 80;
server_name www.youres.cn;
return 301 https://www.youres.cn$request_uri;
}
$request_uri 包含完整原始请求URI(含参数),是最简单可靠的写法。
场景2:旧路径迁移到新路径,保留UTM参数
location /promo/ {
return 301 /new-promo/$is_args$args;
}
场景3:POST接口临时切换到新域名(保留请求体)
location /api/old/ {
return 307 https://api-new.youres.cn/api/new/;
}
七、301/302/307/308 参数处理对比总结
| 状态码 | 是否永久 | 是否保留查询参数 | 是否保留POST请求体 | 典型场景 |
|---|---|---|---|---|
| 301 | 是 | 需手动拼接 | 否(转GET) | 永久迁移 |
| 302 | 否 | 需手动拼接 | 否(转GET) | 临时维护 |
| 307 | 否 | 需手动拼接 | 是 | 临时API切换 |
| 308 | 是 | 需手动拼接 | 是 | 永久API迁移 |
八、常见错误排查
错误1:return后参数重复
# 错误:硬编码?后又拼$is_args$args,导致??
return 301 https://example.com/new/?$is_args$args;
# 修复:
return 301 https://example.com/new/$is_args$args;
错误2:用rewrite的?覆盖原参数后改用return,忘记加拼接
很多人从 rewrite ^(.*)$ /new/$1 permanent; 改用 return 301 后,发现参数丢了——因为 rewrite 的 replacement 里如果没有 ? 会自动附加原参数,而 return 不会。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论