前言
用 Nginx 做 301 重定向时,很多人会遇到这个问题:配置了 return 301 https://example.com/$request_uri,结果跳转后 URL 上的查询参数全丢了。比如 ?utm_source=google&page=2 这种 UTM 参数、广告追踪参数,在重定向后全部消失。
这是 Nginx return 指令的默认行为——不带参数的 return 会丢弃原始的 query string。但这不是无解的,有几种方法可以保留参数,而且每种方法都有它的适用场景。
一、为什么 return 默认不保留参数
先搞清楚原理。Nginx 的 return 指令在处理重定向时,URL 参数的传递规则是这样的:
- return 301 https://newdomain.com; → 目标 URL 不带任何查询参数
- return 301 https://newdomain.com/path; → 只跳转固定路径,原参数丢失
这是 Nginx 的设计逻辑——Nginx 认为,如果你写死了跳转目标,就意味着你不想带参数。参数丢失不是 bug,是预期行为。知道了这个,才能理解怎么修复。
二、三种方法保留参数
方法1:$request_uri 自动带参数(最常用)
server { listen 80; server_name oldsite.com; return 301 https://newsite.com/$request_uri; }原理: $request_uri 变量包含完整的原始 URI,包括查询字符串。例如原始请求是 http://oldsite.com/page?id=5&sort=asc,跳转后变成 https://newsite.com/page?id=5&sort=asc。
适用场景: 整站 HTTP 跳 HTTPS、域名更换且路径保持不变的情况。这是生产环境中最推荐的写法。
注意: 如果目标域名完全换了,路径结构也变了,就不能直接用 $request_uri,否则会把老站的所有参数都带到新站,可能造成问题。
方法2:$is_args + $args 手动拼接(灵活控制)
server { listen 80; server_name oldsite.com; return 301 https://newsite.com/$uri$is_args$args; }原理拆解:
- $uri → 只包含路径部分(不含参数)
- $is_args → 有参数时值为 ?,无参数时为空字符串
- $args → 查询参数字符串(不含 ?)
三者组合:$uri$is_args$args = 完整路径 + 条件性添加 ? + 参数。相当于:有参数时 /page?id=5,无参数时 /page(? 不出现)。
适用场景: 需要对参数做额外处理时,比如只想保留部分参数而不是全部。
方法3:map 指令过滤参数(高级场景)
map $request_uri $redirect_target { ~/utm_source= https://newsite.com/$request_uri; ~/fbclid= https://newsite.com/$request_uri; default https://newsite.com/$uri$is_args$args; } server { listen 80; server_name oldsite.com; return 301 $redirect_target; }通过 map 指令可以灵活判断哪些参数要保留、哪些要去掉。比如可以把追踪参数(utm_source、fbclid)清理掉,只保留业务参数。
三、return 和 rewrite 在参数保留上的对比
| 指令 | 默认行为 | 保留参数方式 | 性能 |
|---|---|---|---|
| return 301 URL | 不带参数(除非 URL 中写明) | 加 $request_uri 或 $is_args$args | 快(直接跳转) |
| rewrite ... redirect | 自动携带参数(默认行为) | 默认保留,不想要需用 ? 清空 | 稍慢(需匹配正则) |
简单说:return 默认丢参数,rewrite 默认带参数。如果你习惯了 rewrite 的行为,用 return 时一定要记得手动加参数变量。
四、典型踩坑场景
场景1:HTTP 跳 HTTPS 后 GA4 追踪失效
这是最常见的场景。配置:
server { listen 80; server_name _; return 301 https://$host$request_uri; }$host 保持原有域名,$request_uri 保留完整路径和参数,UTM 参数不会丢失。
场景2:return 在 location 块中参数丢失
location /old { return 301 https://newsite.com/new$is_args$args; }这个写法会丢失 ? 后面的参数。加上 $is_args$args 即可。
场景3:多级重定向链中参数丢失
如果有多层 return/rewrite,参数可能在某一环丢失。建议保持跳转链尽量简短,并且每级都检查 $request_uri 是否正确传递。
五、验证参数是否保留
配置完不要急着上线,先在本地验证:
curl -I "http://oldsite.com/page?id=5&sort=asc"
看返回头中的 Location,应该是: https://newsite.com/page?id=5&sort=asc。如果 Location 里没有参数,说明配置有问题,回去检查 $request_uri 是否写对了。
六、总结
- 整站重定向:用 return 301 https://$host$request_uri;,简单可靠
- 需要控制参数:用 $uri$is_args$args 手动拼接
- 清理追踪参数:用 map 指令做条件判断
- 不要忘记参数变量:return 默认不带参数是很多人踩坑的根本原因
核心就一句话:用 return 做重定向,记得手动加上 $request_uri 或 $is_args$args,参数才不会丢。
相关阅读
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论