引言
在Nginx配置中,重定向时保留查询参数是很多运维同学的痛点。你可能遇到过这样的情况:配置了HTTP跳转HTTPS,结果URL后面的查询参数全丢了;或者设置了301重定向,UTM追踪参数莫名其妙消失。问题的核心在于$is_args和$args这两个变量的正确拼接。本文通过实战案例,带你彻底掌握URL拼接的正确姿势。
一、先搞清楚三个核心变量
在讨论拼接之前,我们需要先理解三个关键变量的区别:
- $request_uri:完整的请求URI,包含路径和查询字符串,如
/page?id=123&name=test - $uri:只有路径部分,不包含查询字符串,如
/page - $args:只有查询字符串部分,如
id=123&name=test
$is_args是一个特殊的变量:如果请求中有查询参数,它的值是?;如果没有,它的值是空字符串。这个变量是拼接URL的关键。
二、为什么参数总是丢失?
很多同学在配置重定向时,习惯这样写:
return 301 https://example.com$uri;
问题来了:$uri不包含查询参数,所以跳转后参数全部丢失。正确的写法应该是:
return 301 https://example.com$request_uri;
或者使用$is_args和$args组合:
return 301 https://example.com$uri$is_args$args;
三、$is_args和$args拼接的四种场景
场景1:原样保留所有参数
这是最常见的场景,直接使用$request_uri最简单:
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
请求http://example.com/page?id=123&utm_source=google会跳转到https://example.com/page?id=123&utm_source=google,参数完整保留。
场景2:有条件地保留参数
有时你只想保留特定参数,比如只保留UTM参数用于追踪:
location / {
if ($args ~* "utm_") {
return 301 https://example.com$uri?$args;
}
return 301 https://example.com$uri;
}
注意:这里直接写?$args而不是$is_args$args,因为我们确定要加查询字符串。
场景3:添加新参数同时保留原参数
想在跳转时添加新参数,同时保留原有参数:
location /old {
return 301 https://example.com/new$uri$is_args$args&from=old;
}
但这有个问题:如果原请求没有参数,URL会变成/new/page?&from=old,开头多了一个问号。更优雅的写法是:
location /old {
set $new_args "from=old";
if ($args) {
set $new_args "from=old&$args";
}
return 301 https://example.com/new$uri?$new_args;
}
场景4:跨域名跳转保留参数
从旧域名跳转到新域名,同时保留所有参数:
server {
listen 80;
server_name old-domain.com;
return 301 https://new-domain.com$request_uri;
}
四、rewrite指令中的参数处理
rewrite指令的行为和return不同,它有一个特殊规则:rewrite的目标URL如果不以问号结尾,Nginx会自动追加原查询参数。
# 这两种写法效果相同
rewrite ^/old/(.*)$ /new/$1? redirect;
rewrite ^/old/(.*)$ /new/$1 redirect;
但如果你想在rewrite中清空原参数,需要显式加一个问号:
# 清空所有参数
rewrite ^/old/(.*)$ /new/$1? redirect;
注意末尾的问号,这是清空参数的关键。
五、常见错误与排查
错误1:双重问号
错误写法:
return 301 https://example.com$uri?$args;
如果原请求有参数,URL会变成/page?id=123?id=123,出现双重问号。
正确写法:
return 301 https://example.com$uri$is_args$args;
错误2:参数重复
错误写法:
return 301 https://example.com$uri$is_args$args&new=value;
如果原请求没有参数,URL会变成/page?&new=value,开头有一个孤零零的问号。
错误3:$request_uri和$args混用
错误写法:
return 301 https://example.com$request_uri$new_param;
$request_uri已经包含完整路径和参数,不能再追加其他内容。
六、调试技巧
使用curl命令验证重定向是否正确:
curl -I "http://example.com/page?id=123&utm_source=google"
查看Location响应头,确认参数是否完整保留。
也可以在Nginx配置中添加日志:
log_format debug '$request_uri -> $uri$is_args$args';
access_log /var/log/nginx/debug.log debug;
七、最佳实践总结
- 简单重定向保留参数:直接用
$request_uri - 需要修改路径但保留参数:用
$uri$is_args$args - rewrite自动保留参数:不加问号,参数自动追加
- rewrite清空参数:末尾加问号
? - 条件性参数处理:配合
if和set指令
相关文章推荐
- Nginx return 301和rewrite跳转参数保留对比:选对方法让查询字符串不再丢失
- Nginx $is_args $args $request_uri三个变量对比详解:搞懂它们,重定向再也不踩坑
- Nginx $is_args和$args组合用法详解:重定向保留查询参数的正确姿势
结语
掌握$is_args和$args的正确用法,是解决Nginx重定向参数丢失问题的关键。记住核心原则:$request_uri一把梭,复杂场景用$is_args$args。下次遇到参数丢失,先检查你是用的$uri还是$request_uri,再看看有没有双重问号的问题,基本就能定位原因了。
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论