Nginx 配置中,处理 URL 查询参数是日常运维的必修课。很多新手在写 rewrite 规则或者做重定向时,对查询参数的获取方式一知半解,结果要么参数丢失、要么拿不到想要的值。今天就来把 $args 这个变量彻底讲清楚。
什么是 $args 变量
$args 是 Nginx 内置变量,用来存放 HTTP 请求中的查询参数(query string),也就是 URL 中 ? 后面的那部分内容。
举个例子,请求 URL 是:
https://example.com/search?keyword=nginx&page=1&sort=desc
那么 $args 的值就是 keyword=nginx&page=1&sort=desc。它是完整的查询参数字符串,可以直接使用、修改或者拼接。
$args 和 $is_args、$query_string 的区别
这三个变量都和查询参数相关,但各有各的用途,千万别混用:
- $args:查询参数字符串本身,如
keyword=nginx&page=1。没有参数时为空字符串。 - $is_args:一个标志符。如果 URL 中有查询参数则值为
?,没有则为空。这是做条件判断时的好帮手。 - $query_string:功能上等同于 $args,区别在于它是只读的,不能直接赋值修改。
最常见的用法是用 $is_args 判断是否有参数,然后拼接:
set $suffix "$is_args$args";
这样无论原始请求有没有参数,$suffix 都会带上正确的格式(有参数时为 ?keyword=nginx,无参数时为空)。
实战场景一:根据参数值做条件判断
根据查询参数的内容来决定请求的处理方式,是 $args 最常见的用法:
server {
listen 80;
# 根据 utm_source 参数做来源统计
if ($args ~ "utm_source=([^&]+)") {
set $source $1;
add_header X-Source $source;
}
# 过滤掉恶意爬虫参数
if ($args ~ "spider=yes") {
return 403;
}
location / {
root /var/www/html;
index index.html;
}
}
用正则匹配 $args 时,捕获组 $1 可以拿到对应参数的值,这在流量分析和访问控制场景里非常实用。
实战场景二:重定向时保留查询参数
做域名迁移或者 URL 改版时,重定向必须把原有参数带上。来看几个具体写法:
# 方式一:直接拼接(rewrite 默认会追加原参数)
rewrite ^/old-page /new-page redirect;
# 方式二:手动拼接,精确控制
rewrite ^/search/(.*)$ /result?q=$1$is_args$args last;
# 方式三:清空原有参数,重新设置
rewrite ^/search/(.*)$ /result?q=$1? last;
# 注意:结尾加 ? 可以阻止原参数追加
需要特别注意的是,Nginx rewrite 在 replacement 字符串末尾加 ? 会阻止原查询参数追加。如果不加 ?,原参数会自动追加到 replacement 后面。
实战场景三:修改查询参数
有时候需要对参数进行修改,比如给参数加密或者批量替换:
# 将 page 参数值加 10
if ($args ~ "page=(\d+)") {
set $page_num $1;
set $new_page "";
set $remain_args "";
# 实际操作中推荐用 map 配合正则来做参数映射
}
# 用 map 做参数标准化(推荐方式)
map $args $clean_args {
~*&page=(\d+) "page=$1";
~*^ "";
default $args;
}
对于复杂的参数修改,建议使用 map 指令而非在 if 里嵌套太多逻辑。map 在配置解析阶段完成计算,对性能影响更小。
实战场景四:日志中记录查询参数
log_format detailed '$remote_addr - $request_method $request_uri - $args';
server_access_log /var/log/nginx/access_detailed.log detailed;
把 $args 直接写入日志,方便后续用 awk 或者 GoAccess 做流量分析。
常见错误和避坑指南
错误一:在 location 里用 set 修改 $args 后,参数没有生效。
这是因为 $args 是请求级别的变量,在 proxy_pass 之前用 set $args 修改后,需要用 proxy_set_header Query-String $args 或者干脆把参数拼进 proxy_pass 的 URL 里。
# 错误做法
location /api/ {
set $args "page=1"; # 这里改了但 upstream 收不到
proxy_pass http://backend;
}
# 正确做法:把参数写进 proxy_pass 的 URL
location /api/ {
proxy_pass http://backend?page=1;
}
# 或者
location /api/ {
set $new_query "page=1";
proxy_pass http://backend?$new_query;
}
错误二:以为 $args 为空时 $is_args 也为空。
实际上 $is_args 只有两个固定值:有参数时是 ?,无参数时是空字符串。判断时写法要准确:
# 判断有没有参数
if ($is_args = "") {
# 没有查询参数
return 200 "No parameters";
}
# 而不是
if ($is_args = "null") { # 这样永远匹配不到
...
}
错误三:多参数时用字符串截取。
URL 参数里可能有多个同名参数或者特殊字符,直接用字符串截取很容易出错。正确做法是用正则分组来提取:
# 提取 keyword 参数的值(即使后面还有其他参数)
if ($args ~ "(?:^|&)keyword=([^&]+)") {
set $keyword_value $1;
}
总结
$args 是 Nginx 处理 URL 查询参数的核心变量,配合 $is_args 做条件判断、和 rewrite 指令配合做重定向,是每个运维工程师都需要掌握的技能。记住几个要点:
$args是完整的参数字符串,可以修改;$query_string等价但只读。$is_args只返回?或空,用于条件判断。- rewrite 末尾加
?可阻止原参数追加。 - 修改参数后用 proxy_pass 时,要把参数显式传给 upstream。
掌握这些细节,处理查询参数相关的配置时就能少踩坑、提升效率。
相关文章:
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论