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

PHP中CURL PUT请求无法发送JSON数据的问题排查

PHP CURL PUT请求JSON数据无法发送的问题

问题场景

使用PHP的CURL构建PUT请求时,JSON数据始终无法发送到API服务器,通过Fiddler抓包发现请求体为空,服务器返回408 Request body incomplete错误。

相关代码

sendRequest函数实现

public function sendRequest($endpoint, $method, $params = [], $data = null)
{
    $curl = curl_init();
    $url = $this->host . "/" . $endpoint . "?" . http_build_query($params);
    $data = array(
        'ItemCode' => '3505180',
        'SearchCode' => '123456',
    );
    $data_string = json_encode($data);
    switch ($method) {
        case "GET":
            curl_setopt($curl, CURLOPT_HTTPGET, 1);
            break;
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);
            if ($data) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            }
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_PUT, 1);
            
            if ($data) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
            }
            break;
        default:
            break;
    }

    curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:51290');
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        'X-ApiKey: ' . $this->apiKey,
        'administration: ' . $this->administration,
        'Content-Type: application/json'
    ));

    $result = curl_exec($curl);

    if(curl_errno($curl))
    {
        $result = 'Curl error: ' . curl_error($curl);
    }
    curl_close($curl);


    return $result;
}

函数调用代码

public function updateItem($item)
{
    $this->sendRequest("api/Item", "PUT", [], "some json data should go here");
}

抓包及错误信息

原始请求数据

PUT http://appsrv:889/api/Item HTTP/1.1
Host: appsrv:889
Accept: */*
Proxy-Connection: Keep-Alive
X-ApiKey: xxxxx
administration: 002
Content-Type: application/json
Content-Length: 44
Expect: 100-continue

服务器返回错误

HTTP/1.1 408 Request body incomplete
Date: Wed, 17 Aug 2022 07:18:01 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache, must-revalidate
Timestamp: 09:18:01.979

The request body did not contain the specified number of bytes. Got 0, expected 44

问题原因及解决方案

核心原因

  1. CURLOPT_PUT与CURLOPT_POSTFIELDS冲突:当设置CURLOPT_PUT为1时,CURL默认期望从文件读取请求体内容,此时使用CURLOPT_POSTFIELDS无法正确传递内存中的JSON数据,导致实际请求体为空。
  2. 参数覆盖问题:sendRequest函数开头直接硬编码覆盖了传入的$data参数,导致调用时传入的JSON字符串完全失效,即使硬编码的数组被转成JSON,也会因CURL配置错误无法发送。

修复步骤

步骤1:修正PUT请求的CURL配置

移除CURLOPT_PUT设置,改用CURLOPT_CUSTOMREQUEST指定PUT方法,同时保留CURLOPT_POSTFIELDS传递JSON数据:

case "PUT":
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
    if ($data) {
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
    }
    break;

步骤2:保留传入的$data参数

删除函数开头硬编码覆盖$data的代码,根据传入参数的类型处理JSON转换:

// 移除硬编码覆盖的代码
// $data = array(
//     'ItemCode' => '3505180',
//     'SearchCode' => '123456',
// );

// 改为动态处理传入的$data
$data_string = '';
if ($data) {
    $data_string = is_array($data) ? json_encode($data) : $data;
}

步骤3:确保Content-Length正确(可选)

虽然CURL会自动计算Content-Length,但针对代理或特殊服务器场景,可以手动设置:

$headers = array(
    'X-ApiKey: ' . $this->apiKey,
    'administration: ' . $this->administration,
    'Content-Type: application/json'
);
if (!empty($data_string)) {
    $headers[] = 'Content-Length: ' . strlen($data_string);
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

修复后的完整sendRequest函数

public function sendRequest($endpoint, $method, $params = [], $data = null)
{
    $curl = curl_init();
    $url = $this->host . "/" . $endpoint . "?" . http_build_query($params);
    
    $data_string = '';
    if ($data) {
        $data_string = is_array($data) ? json_encode($data) : $data;
    }

    switch ($method) {
        case "GET":
            curl_setopt($curl, CURLOPT_HTTPGET, 1);
            break;
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);
            if ($data) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
            }
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
            if ($data) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
            }
            break;
        default:
            break;
    }

    curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:51290');
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    
    $headers = array(
        'X-ApiKey: ' . $this->apiKey,
        'administration: ' . $this->administration,
        'Content-Type: application/json'
    );
    if (!empty($data_string)) {
        $headers[] = 'Content-Length: ' . strlen($data_string);
    }
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

    $result = curl_exec($curl);

    if(curl_errno($curl))
    {
        $result = 'Curl error: ' . curl_error($curl);
    }
    curl_close($curl);

    return $result;
}

修正后的调用方式

public function updateItem($item)
{
    // 可传入数组或JSON字符串
    $updateData = array(
        'ItemCode' => '3505180',
        'SearchCode' => '123456'
    );
    $this->sendRequest("api/Item", "PUT", [], $updateData);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 22:15:36