0

Nginx rewrite重定向保留查询参数:5种场景+完整配置示例

2026.05.26 | youres | 10次围观

很多运维朋友在配置 Nginx 重定向时经常会遇到这个问题:用户访问 http://example.com/old-page?id=123,结果被重定向到了 https://example.com/new-page,查询参数 ?id=123 莫名其妙就丢了。这种情况在页面迁移、域名切换、HTTPS 强制跳转等场景下特别常见——参数丢了不说,SEO 权重也跟着打水漂,用户体验更是直接崩掉。

今天这篇就来说清楚:Nginx 重定向时如何保留原始 URL 的查询参数,5 种常见场景 + 完整配置示例,一次搞懂。

一、先搞懂 query string 是怎么回事

在 Nginx 里,URL 分为两部分:一部分是路径(URI),另一部分是查询字符串(query string)。举个例子:

http://example.com/search?q=nginx&page=2
  • 路径部分(URI):/search
  • 查询字符串(query string):q=nginx&page=2

Nginx 提供了一系列变量来处理这两部分:

  • $request_uri — 完整请求 URI,包含路径和查询参数,如 /search?q=nginx&page=2
  • $uri — 仅路径部分,不含查询参数,如 /search
  • $args — 仅查询参数部分,如 q=nginx&page=2
  • $is_args — 如果有查询参数则等于 ?,没有则为空字符串

记住这四个变量的区别,是理解所有重定向配置的基础。

二、return 指令:需要手动拼接参数

return 指令是最简单的重定向方式,但默认不会自动携带查询参数。看个例子:

server {
    listen 80;
    server_name example.com;
    # 简单重定向,不保留参数
    return 301 https://example.com$uri;
}

用户访问 http://example.com/old?id=5,会被重定向到 https://example.com/old,参数 ?id=5 直接丢失。

要在 return 中保留参数,需要手动拼接:

server {
    listen 80;
    server_name example.com;
    # 保留查询参数的写法
    return 301 https://example.com$uri$is_args$args;
}

这样 $is_args 会判断是否有参数(有就变成 ?,没有就为空),$args 则是参数本身。访问 http://example.com/old?id=5 就会正确跳转到 https://example.com/old?id=5

三、rewrite 指令:默认行为与参数控制

1. rewrite 默认保留参数

return 不同,rewrite 指令在重定向时默认会携带查询参数。看这个配置:

server {
    listen 80;
    server_name example.com;
    rewrite ^/old-page/(.*)$ /new-page/$1 redirect;
}

用户访问 http://example.com/old-page/product?id=42,会被重定向到 https://example.com/new-page/product?id=42,参数自动保留。

2. 如果不想保留参数,加上 query string 覆盖

rewrite ^/old-page/(.*)$ /new-page/$1? drop redirect;

在重写目标后加一个 ?,就可以丢弃原参数。这里的 ? 是 Nginx rewrite 的特殊语法,用来清空查询参数。

3. rewrite 中自定义参数

rewrite ^/old-page/(.*)$ /new-page/?category=$1&from=old redirect;

这样访问 http://example.com/old-page/tech?id=99,会被重定向到 https://example.com/new-page/?category=tech&from=old&id=99——注意,原始参数仍然追加在后面。如果只想完全替换参数(不追加原始参数),需要用 capture 加问号。

四、5 种常见场景配置

场景1:HTTP 强制跳转到 HTTPS,保留所有参数

server {
    listen 80;
    server_name www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    server_name www.example.com;
    # 业务配置
}

$request_uri 是最简单的方式,它包含了完整的路径和查询参数。注意:这个配置只对标准端口(80/443)有效。

场景2:单个页面迁移,参数完整传递

server {
    listen 80;
    server_name www.example.com;
    
    # 旧页面跳转到新页面
    location = /old-product {
        return 301 https://www.example.com/products$is_args$args;
    }
}

用户访问 http://www.example.com/old-product?ref=google&id=789,会跳转到 https://www.example.com/products?ref=google&id=789

场景3:多路径批量重定向

server {
    listen 80;
    server_name www.example.com;
    
    # 博客文章迁移 /blog/2018/xxx -> /articles/xxx
    rewrite ^/blog/\d{4}/(.*)$ /articles/$1? redirect;
    
    # 标签页迁移
    rewrite ^/tag/(.*)$ /topics/$1? redirect;
    
    # 默认 fallback
    return 301 https://www.example.com$request_uri;
}

场景4:多域名合并跳转,参数不丢失

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

所有从旧域名过来的请求,包括带参数的搜索结果页、筛选条件等,都会完整保留到新域名。

场景5:API 版本迁移,查询参数作为路由依据

server {
    listen 80;
    server_name api.example.com;
    
    # v1 API 跳转到 v2,保留分页和过滤参数
    location /api/v1/ {
        return 301 https://api.example.com/api/v2$uri$is_args$args;
    }
}

用户访问 http://api.example.com/api/v1/users?role=admin&page=3,会跳转到 https://api.example.com/api/v2/users?role=admin&page=3

五、最容易踩的几个坑

坑1:return 和 rewrite 混用时参数行为不一致

同一套配置里,如果既有 return 又有 rewrite,要注意它们的参数保留逻辑不同。解决方案是统一用一种方式,或者明确在每个 return 里手动拼接参数。

坑2:HTTPS 跳转时用了 $uri 而不是 $request_uri

这是最常见的丢失参数的情况。HTTP 跳 HTTPS 时:

# 错误写法 - 参数丢失
return 301 https://$host$uri;

# 正确写法 - 参数完整
return 301 https://$host$request_uri;

坑3:重定向后参数被重复追加

如果 rewrite 里用了 ? 清空参数,但配置里又有其他 rewrite 导致参数追加两次,就会出现形如 ?id=5&id=5 的重复参数。解决方法是确保每个 rewrite 的目标地址只有一个带 ? 的地方。

坑4:if 条件里访问 $args 的方式不对

if 条件判断中想要根据参数值做跳转,需要用正则匹配:

if ($request_uri ~ "^/old-page\?ref=google") {
    return 301 https://www.example.com/new-page?source=google;
}

六、调试技巧

如果配置完发现参数还是丢了,或者重定向链不对,可以用以下命令检查配置是否正确:

nginx -t

加载完整配置并查看最终生效的重定向行为:

nginx -T

另外,也可以用 curl 来验证跳转是否正确:

curl -I "http://example.com/old-page?id=123"

看返回的 Location 头里是否包含了完整的查询参数。

总结

Nginx 重定向保留查询参数的核心就三点:

  1. return 指令:需要手动拼接 $uri$is_args$args 才能保留参数
  2. rewrite 指令:默认保留参数,如果想丢弃或替换需要加 ?
  3. HTTP 跳 HTTPS:推荐用 $request_uri 自动包含完整 URI

把这两个指令的参数处理逻辑区分清楚,重定向配置就不再是问题。参数保留看似小事,但对 SEO 和用户体验的影响却是实打实的。

相关推荐阅读:

版权声明

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

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