You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本中通过CURL GET请求传递JSON解析变量时遭遇URL格式错误问题求助

解决curl请求URL格式错误及JSON解析问题

咱们一步步排查并修复你的脚本问题:

1. 核心错误:JSON解析方式完全错误

你当前的写法ruleId=$($whitelist | jq '.[].ruleId')是根本问题——$whitelist是文件名,不是可执行命令,shell会尝试把文件名当作命令运行,直接导致变量值异常,进而污染curl的请求参数,引发URL格式错误。

正确的做法是让jq直接读取文件,或者用cat传递文件内容给jq:

# 推荐方式:jq直接读取文件
ruleId=$(jq -r '.[].ruleId' "$whitelist")
# 备选方式:用cat传递文件内容
ruleId=$(cat "$whitelist" | jq -r '.[].ruleId')

2. 必须去掉jq输出的双引号

默认情况下,jq输出的字符串会自带双引号(比如"1001"),如果直接把这个值传给curl,会导致参数里包含多余的引号,破坏请求格式。加上-r(raw output)参数可以让jq输出不带引号的纯字符串。

3. 处理JSON数组的循环问题

你的JSON是一个数组结构,.[].ruleId会输出数组中所有元素的ruleId,如果数组有多个元素,变量会被赋值为多个值用空格分隔,导致curl参数混乱。你需要循环遍历数组中的每个元素:

# 遍历JSON数组中的每个对象
jq -c '.[]' "$whitelist" | while read -r item; do
    # 从单个对象中提取字段,-r确保输出无引号
    ruleId=$(echo "$item" | jq -r '.ruleId')
    alert=$(echo "$item" | jq -r '.alertName')
    newLevel=$(echo "$item" | jq -r '.newLevel')
    url=$(echo "$item" | jq -r '.url')
    urlIsRegex=$(echo "$item" | jq -r '.urlIsRegex')
    enabled=$(echo "$item" | jq -r '.enabled')
    parameter=$(echo "$item" | jq -r '.parameter')
    evidence=$(echo "$item" | jq -r '.evidence')

    # 执行curl请求
    curl --data-urlencode "ruleId=$ruleId" \
         --data-urlencode "newLevel=$newLevel" \
         --data-urlencode "url=$url" \
         --data-urlencode "urlIsRegex=$urlIsRegex" \
         --data-urlencode "enabled=$enabled" \
         --data-urlencode "parameter=$parameter" \
         --data-urlencode "evidence=$evidence" \
         "http://localhost:8080/JSON/alertFilter/action/addGlobalAlertFilter"
done

4. 关于curl请求方法的补充说明

注意:使用--data-urlencode参数时,curl默认会发送POST请求,而非GET请求。如果你的API确实要求GET,需要手动将编码后的参数拼接到URL后:

# GET请求示例:手动编码并拼接参数
encoded_ruleId=$(printf "%s" "$ruleId" | xargs printf "%q")
encoded_url=$(printf "%s" "$url" | xargs printf "%q")

curl "http://localhost:8080/JSON/alertFilter/action/addGlobalAlertFilter?ruleId=$encoded_ruleId&newLevel=$newLevel&url=$encoded_url..."

不过从API路径/addGlobalAlertFilter来看,更可能接受POST请求,所以原有的--data-urlencode方式是合适的。

完整修复后的脚本

#!/bin/sh
#set -e
# 测试脚本说明
# 1. 启动docker
# 2. 在终端运行命令:docker run -u zap -p 8080:8090 -i owasp/zap2docker-stable zap.sh -daemon -host 0.0.0.0 -port 8080 -config api.disablekey=true -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true
# 3. 从API获取JSON(当前为测试用)
# 4. 执行bash filter.sh
# 5. 通过浏览器http://localhost:8080/UI/alertFilter/ 查看已设置的全局过滤器

# 下载示例JSON到临时文件
curl -s 'https://api.npoint.io/c29e3a68be632f73fc22' > whitelist_tmp.json
whitelist=whitelist_tmp.json

# 遍历JSON数组中的每个告警规则对象
jq -c '.[]' "$whitelist" | while read -r item; do
    # 提取每个字段并去掉jq默认的双引号
    ruleId=$(echo "$item" | jq -r '.ruleId')
    alert=$(echo "$item" | jq -r '.alertName')
    newLevel=$(echo "$item" | jq -r '.newLevel')
    url=$(echo "$item" | jq -r '.url')
    urlIsRegex=$(echo "$item" | jq -r '.urlIsRegex')
    enabled=$(echo "$item" | jq -r '.enabled')
    parameter=$(echo "$item" | jq -r '.parameter')
    evidence=$(echo "$item" | jq -r '.evidence')

    echo "正在添加规则ID为 $ruleId 的全局告警过滤器..."
    # 发送curl请求
    curl --data-urlencode "ruleId=$ruleId" \
         --data-urlencode "newLevel=$newLevel" \
         --data-urlencode "url=$url" \
         --data-urlencode "urlIsRegex=$urlIsRegex" \
         --data-urlencode "enabled=$enabled" \
         --data-urlencode "parameter=$parameter" \
         --data-urlencode "evidence=$evidence" \
         "http://localhost:8080/JSON/alertFilter/action/addGlobalAlertFilter"
done

# 清理临时文件
rm "$whitelist"

现在运行这个修复后的脚本,应该就能正常发送请求并添加全局告警过滤器了。

内容的提问来源于stack exchange,提问作者t30_9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:44:20