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

Shell脚本中使用curl发起HTTP请求返回404问题求助

带重试逻辑的Shell curl函数返回404问题排查

我编写了一个带重试逻辑的Shell脚本函数sendWithRetry,该函数接收URL和若干参数,用于构造并执行curl请求,但调用后返回404错误,怀疑是函数参数传递方式导致的。

函数代码

function sendWithRetry() {

    local _URL="$1"
    local _CURL_ARGS="${@:2}"
    RESPONSE=""
    for x in {0..20} ;
    do
        
        echo "Sending request to $_URL"
        cat ${CALLBACK_REQUEST_IPV4_HTTPS}
        echo "Executing : curl --connect-timeout 1 -f -s ${_CURL_ARGS} $_URL "
        RESPONSE=$(curl --connect-timeout 1 -f -s ${_CURL_ARGS} $_URL) && break

    done

    if [ $x -lt 20 ] ;
    then
        echo "Request $_URL sent successfully!!!"
        echo "Response: $RESPONSE"
    else
        echo "Failed to send request to $_URL!!!"
        exit 1
    fi
}

调用代码片段

if ! sendWithRetry "${TEST_URL_HTTPS}" -k -X POST -H '"Content-Type: application/json"' -d @${CALLBACK_REQUEST_IPV4_HTTPS}
then
    echo "Test failed!!!"
    exit 1
fi

执行日志

[INFO]      [exec] # $$ echo "Sending request to $_URL"
[INFO]      [exec] # Sending request to https://192.168.16.5:31444/service-b/v1/subscribe?p2=test
[INFO]      [exec] # $$ cat ${CALLBACK_REQUEST_IPV4_HTTPS}
[INFO]      [exec] # {
[INFO]      [exec] #     "testname": "service-b makes a callback request to service-a over IPv4 & HTTPS protocol",
[INFO]      [exec] #     "Uri": "https://192.168.16.5:30443/callback/service-b/v1/handleNotify",
[INFO]      [exec] #     "p3": "param-3",
[INFO]      [exec] #     "p5": "param-5"
[INFO]      [exec] # }$$ echo "Executing : curl --connect-timeout 1 -f  ${_CURL_ARGS} $_URL "
[INFO]      [exec] # Executing : curl --connect-timeout 1 -f  -v -k -X POST -H "Content-Type: application/json" -d @/test/scripts/tests/dual-stack/callback-flow/callbackRequestIpv4Https.json https://192.168.16.5:31444/service-b/v1/subscribe?p2=test
[INFO]      [exec] # $$ RESPONSE=$(curl --connect-timeout 1 -f -s ${_CURL_ARGS} $_URL)
[INFO]      [exec] # $$ curl --connect-timeout 1 -f -s ${_CURL_ARGS} $_URL
[INFO]      [exec] # * Could not resolve host: application
[INFO]      [exec] # * Closing connection
[INFO]      [exec] # *   Trying 192.168.16.5:31444...
[INFO]      [exec] # * Connected to 192.168.16.5 (192.168.16.5) port 31444
[INFO]      [exec] # * ALPN: curl offers h2,http/1.1
[INFO]      [exec] # } [5 bytes data]
[INFO]      [exec] # * TLSv1.3 (OUT), TLS handshake, Client hello (1):
[INFO]      [exec] # } [512 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Server hello (2):
[INFO]      [exec] # { [122 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
[INFO]      [exec] # { [15 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Request CERT (13):
[INFO]      [exec] # { [83 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Certificate (11):
[INFO]      [exec] # { [670 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, CERT verify (15):
[INFO]      [exec] # { [264 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Finished (20):
[INFO]      [exec] # { [52 bytes data]
[INFO]      [exec] # * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
[INFO]      [exec] # } [1 bytes data]
[INFO]      [exec] # * TLSv1.3 (OUT), TLS handshake, Certificate (11):
[INFO]      [exec] # } [8 bytes data]
[INFO]      [exec] # * TLSv1.3 (OUT), TLS handshake, Finished (20):
[INFO]      [exec] # } [52 bytes data]
[INFO]      [exec] # * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS
[INFO]      [exec] # * ALPN: server accepted h2
[INFO]      [exec] # * Server certificate:
[INFO]      [exec] # *  subject: O=Openet; CN=Ingress for svc-b-ingress
[INFO]      [exec] # *  start date: Oct 14 08:30:17 2024 GMT
[INFO]      [exec] # *  expire date: Apr 12 08:30:17 2025 GMT
[INFO]      [exec] # *  issuer: O=Openet; CN=Openet Test CA
[INFO]      [exec] # *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
[INFO]      [exec] # *   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using ecdsa-with-SHA256
[INFO]      [exec] # } [5 bytes data]
[INFO]      [exec] # * using HTTP/2
[INFO]      [exec] # * [HTTP/2] [1] OPENED stream for https://192.168.16.5:31444/service-b/v1/subscribe?p2=test
[INFO]      [exec] # * [HTTP/2] [1] [:method: POST]
[INFO]      [exec] # * [HTTP/2] [1] [:scheme: https]
[INFO]      [exec] # * [HTTP/2] [1] [:authority: 192.168.16.5:31444]
[INFO]      [exec] # * [HTTP/2] [1] [:path: /service-b/v1/subscribe?p2=test]
[INFO]      [exec] # * [HTTP/2] [1] [user-agent: curl/8.8.0]
[INFO]      [exec] # * [HTTP/2] [1] [accept: */*]
[INFO]      [exec] # * [HTTP/2] [1] [content-length: 209]
[INFO]      [exec] # * [HTTP/2] [1] [content-type: application/x-www-form-urlencoded]
[INFO]      [exec] # } [5 bytes data]
[INFO]      [exec] # > POST /service-b/v1/subscribe?p2=test HTTP/2
[INFO]      [exec] # > Host: 192.168.16.5:31444
[INFO]      [exec] # > User-Agent: curl/8.8.0
[INFO]      [exec] # > Accept: */*
[INFO]      [exec] # > Content-Length: 209
[INFO]      [exec] # > Content-Type: application/x-www-form-urlencoded
[INFO]      [exec] # >
[INFO]      [exec] # } [209 bytes data]
[INFO]      [exec] # * upload completely sent off: 209 bytes
[INFO]      [exec] # { [5 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
[INFO]      [exec] # { [230 bytes data]
[INFO]      [exec] # * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
[INFO]      [exec] # { [230 bytes data]
[INFO]      [exec] # * old SSL session ID is stale, removing
[INFO]      [exec] # { [5 bytes data]
[INFO]      [exec] # < HTTP/2 404
[INFO]      [exec] # < content-type: application/problem+json
[INFO]      [exec] # < 3gpp-sbi-message-priority: 24
[INFO]      [exec] # < content-length: 37
[INFO]      [exec] # < x-envoy-upstream-service-time: 1
[INFO]      [exec] # < date: Mon, 14 Oct 2024 15:05:10 GMT
[INFO]      [exec] # < server: PCF-91fd8c65-677a-4292-9333-376ba9649ffd
[INFO]      [exec] # <
[INFO]      [exec] # * The requested URL returned error: 404

问题分析

从日志里能看到两个核心问题:

  1. 出现* Could not resolve host: application错误,说明Content-Type的参数被错误拆分,curl把application当成了主机名
  2. 实际发送的请求中,Content-Type被自动设为application/x-www-form-urlencoded,而非我们指定的application/json,这会导致服务器无法正确解析请求体,进而返回404

根本原因

  • 调用参数错误:调用函数时,-H '"Content-Type: application/json"'多嵌套了一层引号,导致shell解析时把"Content-Type:和application"拆成了两个独立参数
  • 函数参数传递错误:函数中用local _CURL_ARGS="${@:2}"将剩余参数拼接成字符串,这种方式会破坏参数的原始结构,带空格的参数会被错误拆分

修复方案

1. 修正调用代码的Header参数

去掉Header参数中多余的嵌套引号:

if ! sendWithRetry "${TEST_URL_HTTPS}" -k -X POST -H "Content-Type: application/json" -d @${CALLBACK_REQUEST_IPV4_HTTPS}
then
    echo "Test failed!!!"
    exit 1
fi

2. 修改函数的参数传递方式

使用数组保存curl参数,避免字符串拼接导致的参数拆分问题:

function sendWithRetry() {
    local _URL="$1"
    shift  # 移除第一个URL参数,剩余参数均为curl参数
    local _CURL_ARGS=("$@")  # 用数组保存参数,保留原始结构
    RESPONSE=""
    
    for x in {0..20}; do
        echo "Sending request to $_URL"
        cat "${CALLBACK_REQUEST_IPV4_HTTPS}"
        # 打印执行命令时,用引号包裹数组元素,方便调试
        echo "Executing : curl --connect-timeout 1 -f -s ${_CURL_ARGS[@]@Q} $_URL "
        # 使用数组展开方式传递参数,保证每个参数的完整性
        RESPONSE=$(curl --connect-timeout 1 -f -s "${_CURL_ARGS[@]}" "$_URL") && break
    done

    if [ "$x" -lt 20 ]; then
        echo "Request $_URL sent successfully!!!"
        echo "Response: $RESPONSE"
    else
        echo "Failed to send request to $_URL!!!"
        exit 1
    fi
}

修复说明

  • 用shift配合数组_CURL_ARGS=("$@")保存curl参数,能完整保留带空格或特殊字符的参数结构
  • 调用curl时使用"${_CURL_ARGS[@]}"展开数组,确保每个参数作为独立项被curl接收
  • 调试打印时用${_CURL_ARGS[@]@Q}可以显示带引号的参数原始形态,方便排查问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:39:54