0

Nginx重定向拼接URL实战:$is_args和$args的正确用法

2026.05.29 | youres | 5次围观

引言

在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;

七、最佳实践总结

  1. 简单重定向保留参数:直接用$request_uri
  2. 需要修改路径但保留参数:用$uri$is_args$args
  3. rewrite自动保留参数:不加问号,参数自动追加
  4. rewrite清空参数:末尾加问号?
  5. 条件性参数处理:配合ifset指令

相关文章推荐

结语

掌握$is_args和$args的正确用法,是解决Nginx重定向参数丢失问题的关键。记住核心原则:$request_uri一把梭,复杂场景用$is_args$args。下次遇到参数丢失,先检查你是用的$uri还是$request_uri,再看看有没有双重问号的问题,基本就能定位原因了。

版权声明

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

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