0

Nginx return 301和302在参数处理上的区别:参数丢失、POST请求、307/308替代方案全解析

2026.05.29 | youres | 9次围观

前言

用 Nginx 做重定向,很多人分不清 return 301return 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辅助作者原创,未经许可,转载请保留原文链接。

发表评论
882文章数 0评论数
作者其它文章