很多站长在做HTTP到HTTPS的301重定向后,会碰到一个让人头疼的问题:网站的分页功能失效了。用户点击第2页、第3页,跳转过去后直接回到第1页,或者页面报404。排查半天,最后发现是分页参数page=2在HTTPS跳转过程中被丢掉了。
这个问题表面上只是分页不好用,实际上影响的范围更广——任何带查询参数的URL,包括筛选条件、排序方式、搜索关键词,都可能在HTTPS重定向中消失。本文针对分页参数这个最典型的场景,从根本原因到4种解决方案,给你讲透彻。
一、分页参数为什么会在HTTPS跳转中丢失?
首先要搞清楚一件事:HTTPS跳转本身不会删除查询参数。问题的根源出在Nginx的重定向写法上。
假设你的原始URL是:
http://www.example.com/article-list?page=2
正确的重定向应该跳转到:
https://www.example.com/article-list?page=2
但实际上,很多人在Nginx里写重定向时,page=2这个查询字符串被截断了。常见的原因有以下几种:
1. 用了 rewrite 替换了整个URI
当你使用 rewrite ^(.*)$ https://$host$1 permanent; 时,$1只捕获路径部分,不包含查询参数。这导致跳转后的URL丢失了 ?page=2。
2. return 指令没带 $request_uri
如果写成了 return 301 https://$host$uri;,$uri 变量不包含查询字符串。必须用 $request_uri 才能保留完整的路径加参数。
3. rewrite 目标URL带了问号但没拼接参数
类似 rewrite ^(.*)$ https://$host$1? permanent; 的写法,虽然加了问号,但没有把原始参数追加上去,等于主动清空了查询字符串。
二、4种解决方案,从简单到进阶
方案一:return 301 + $request_uri(最推荐)
这是最简单、最可靠的写法。$request_uri 变量会原封不动地保留完整的请求URI,包括路径和查询参数。
server {
listen 80;
server_name www.example.com;
return 301 https://$host$request_uri;
}
跳转效果:
http://www.example.com/article-list?page=2
→ https://www.example.com/article-list?page=2 ✅ 参数完好
优点:写法简洁,一行搞定,性能也好(return指令不需要正则匹配)。
缺点:几乎没有,这是官方推荐的最佳实践。
方案二:rewrite + $is_args$args
如果你已经在用 rewrite 做其他重写规则,可以在HTTPS跳转时这样写:
server {
listen 80;
server_name www.example.com;
rewrite ^ https://$host$request_uri?$args permanent;
}
或者更精确地拼接:
server {
listen 80;
server_name www.example.com;
rewrite ^(.*)$ https://$host$1$is_args$args permanent;
}
这里 $is_args 在有查询参数时等于 ?,没有参数时为空。$args 是查询参数的值。两者配合,就能在参数存在时正确拼接,不存在时不加多余的问号。
适用场景:需要同时做路径重写和HTTPS跳转的情况。
方案三:return 301 拼接 $is_args$args
如果你想在 return 指令中明确控制参数拼接逻辑,可以这样:
server {
listen 80;
server_name www.example.com;
return 301 https://$host$uri$is_args$args;
}
注意这里用的是 $uri(只有路径)而不是 $request_uri,所以必须手动加上 $is_args$args。
跳转效果和方案一完全一致:
http://www.example.com/article-list?page=2
→ https://www.example.com/article-list?page=2 ✅
适用场景:需要对路径做额外处理(比如去掉或添加前缀)时。
方案四:if 判断 + return(按需保留参数)
有时候你不想保留所有参数,只想保留 page 参数,丢弃其他干扰参数。可以用 map 指令来筛选:
map $args $filtered_args {
~(^|&)page=([^&]*)&?(.*) page=$2&$3;
default "";
}
server {
listen 80;
server_name www.example.com;
return 301 https://$host$uri?$filtered_args;
}
这样就能精确控制只保留 page 参数,其他参数一律过滤掉。
适用场景:参数较多,只想保留特定参数(如page、sort)的场景。
三、快速验证:用curl测试参数是否保留
改完配置后,不要只靠浏览器测试。用 curl 可以精确看到重定向过程:
curl -I http://www.example.com/article-list?page=2
关注输出中的 Location 头:
HTTP/1.1 301 Moved Permanently
Server: nginx
Location: https://www.example.com/article-list?page=2
如果 Location 末尾没有 ?page=2,说明参数丢了,需要回头检查配置。
用 -L 参数可以跟随重定向,查看最终页面:
curl -L http://www.example.com/article-list?page=2
四、分页参数丢失的常见排查清单
如果你按照上面的方案配了但还是不行,对照这个清单逐条检查:
- ❶ 检查 $request_uri vs $uri:确认用的是
$request_uri(含参数)而不是$uri(不含参数) - ❷ 检查 rewrite 目标是否自带问号:
rewrite ^ https://$host$1? permanent中的问号会清空参数 - ❸ 检查 CDN 层是否拦截:Cloudflare、阿里云CDN的"始终使用HTTPS"功能可能重写了URL,参数在CDN层就被丢掉了
- ❹ 检查 proxy_redirect 配置:反向代理场景下,
proxy_redirect可能改写了 Location 头 - ❺ 检查浏览器缓存:浏览器可能缓存了旧的重定向结果,用隐身模式测试
- ❻ 检查 nginx -t 是否有语法错误:配置错误可能导致部分指令不生效
五、总结:选哪个方案?
| 方案 | 写法 | 推荐度 | 适用场景 |
|---|---|---|---|
| 方案一 | return 301 https://$host$request_uri | ⭐⭐⭐⭐⭐ | 绝大多数HTTP到HTTPS跳转 |
| 方案二 | rewrite + $is_args$args | ⭐⭐⭐⭐ | 需要同时做路径重写 |
| 方案三 | return 301 + $uri$is_args$args | ⭐⭐⭐⭐ | 需要对路径做额外处理 |
| 方案四 | map过滤 + return | ⭐⭐⭐ | 只需保留特定参数 |
对于90%以上的场景,直接用方案一就够了。一句话:return 301 https://$host$request_uri;,简单、高效、不丢参数。别想太多,先试这个。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论