0

Nginx return 301 保留所有参数不丢失:3种实战配置详解

2026.05.28 | youres | 11次围观

前言

用Nginx做301永久重定向时,很多人会遇到这样的问题:配置写好了,浏览器跳转也正常,但跳转后的URL里查询参数全丢了。比如用户访问 https://old.com/page?id=123&from=baidu,跳转后变成了 https://new.com/page,后面的 ?id=123&from=baidu 凭空消失。

这个问题在SEO、流量追踪、登录态传递等场景下影响很大。本文就来讲清楚:Nginx的return指令为什么会丢参数,以及怎么配置才能把参数完整保留下来。

一、先搞懂为什么参数会丢失

看一个最常见的错误配置:

server {
    listen 80;
    server_name old.com;
    return 301 https://new.com;
}

看起来已经用了 ,参数应该保留才对。但实际上,很多场景下这个配置依然会丢参数,原因是 本身包含了原始的查询字符串(/path?query=value),但如果Nginx在处理过程中经过了 proxy_pass 或者其他中间层,查询参数可能被过滤掉了。

更常见的问题是直接在 location 块里用了类似这样的写法:

location / {
    return 301 https://new.com/;
}

这种写法只跳转到根路径 /,所有路径和参数全部丢失,跟没说一样。

二、3种实战配置:完整保留参数不丢失

方法1:用 保留完整原始URL

这是最直接的做法。 包含了原始请求的完整路径(含查询字符串)。

server {
    listen 80;
    server_name old.com www.old.com;
    return 301 https://new.com;
}

效果:访问 http://old.com/article?id=5&ref=google → 跳转到 https://new.com/article?id=5&ref=google,参数原封不动。

适用场景:整站迁移、域名更换、HTTP强制跳转HTTPS。

方法2:用 手动拼接参数

是解码后的路径(不含查询参数), 在有参数时返回 ? 是查询参数字符串。三者拼接即可还原完整URL:

server {
    listen 80;
    server_name old.com;
    return 301 https://new.com;
}

效果同上,但写法更明确可控。在某些经过内部重写(rewrite)之后的场景,用 更可靠,因为它不受rewrite过程的影响。

适用场景:经过rewrite处理后的重定向、需要精确控制路径拼接的场景。

方法3:用map指令按需保留特定参数

有时候不需要保留全部参数,只想保留特定参数(如 utm_source),其余参数过滤掉避免干扰。可以结合 map 指令实现:

# 在http块中定义map
map   {
    ~*^.*?(utm_source=[^&]+&?.*)$ ;
    default "";
}

server {
    listen 80;
    server_name old.com;
    set  "https://new.com/";
    if ( != "") {
        set  "https://new.com/?";
    }
    return 301 ;
}

这个写法相对复杂,但如果你做营销归因只想保留UTM参数,这种方式更干净。

适用场景:精准营销归因、只想保留特定参数的场景。

三、return 301 vs rewrite 在参数保留上的区别

很多同学会拿rewrite和return做对比。简单说:

  • return:直接终止请求并返回响应(跳转),参数处理取决于你写的目标URL。
  • rewrite:在server块内做路径重写,默认保留查询参数,但用 rewrite ... break 或带 ? 的写法时也会清空参数。

两者的参数行为其实是一致的关键在于你写目标URL时有没有显式包含参数部分。

四、实战场景:HTTP强制跳转HTTPS保留所有参数

这是最常见的使用场景。正确的写法:

server {
    listen 80;
    server_name _;
    return 301 https://System.Management.Automation.Internal.Host.InternalHost;
}

server {
    listen 443 ssl http2;
    server_name _;
    # SSL配置省略...
    # 正常处理请求
}

注意这里用的是 System.Management.Automation.Internal.Host.InternalHost 而不是硬编码域名。System.Management.Automation.Internal.Host.InternalHost 会自动取当前访问的域名,更灵活,适合泛域名场景。

之前写过一篇 《Nginx rewrite重定向保留查询参数:5种场景+完整配置示例》,对rewrite和return的差异有更详细的对比,感兴趣的可以参考。

五、用curl验证参数是否完整保留

配置完后不要光靠浏览器看,浏览器会自动补全很多参数。用curl能看得更清楚:

# 直接查看301跳转后的Location头
curl -I -L http://old.com/page?id=123 2>/dev/null | grep -i location

# 对比两种写法的区别
curl -s -w "%{url_effective}\n" -o /dev/null "http://old.com/search?q=nginx&page=1"

如果Location头里包含了完整的查询参数,说明配置正确。

另外,Chrome浏览器可以用开发者工具 → Network → 点击那条301请求,查看Response Headers里的 Location 字段是否包含完整参数。

六、参数丢失的常见排查方向

如果配置了但参数还是丢了,从以下几个方向排查:

  1. 中间是否有CDN或负载均衡:Cloudflare、阿里云CDN等会在边缘层过滤参数,需要在CDN控制台单独配置"保留查询参数"。
  2. 是否经过了proxy_pass:Nginx作为反向代理时,proxy_pass本身不会丢参数,但配合return使用时要确保写在proxy_pass之前。
  3. :有同学会写成 /(多了一个斜杠),这样会把参数部分变成路径的一部分,导致参数丢失。
  4. 缓存问题:浏览器或CDN可能缓存了旧的301响应,清缓存后再测试。

总结

Nginx return 301 保留参数的核心就一句话:在目标URL里显式加上查询字符串。

三种方法的推荐顺序是:

  1. 优先用 return 301 https://new.com; ——最简洁,适用于大多数场景。
  2. 需要精确控制时用 return 301 https://new.com;
  3. 精准过滤参数时用map配合return。

记住这个原则,基本就不会再踩坑了。

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

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