PHP使用cURL请求HTTP/2接口无代理时响应Body乱码无法解析
问题根因
- 开启Burp/ZAP代理时,代理会自动解压服务端返回的gzip压缩响应后再转发,因此你拿到的响应体是明文可直接解析
- 关闭代理后,cURL默认未开启自动解压配置,你拿到的响应体是gzip压缩后的二进制数据,
json_decode解析失败返回null,访问数组偏移就触发了对应的报错
修复方案
方案1:开启cURL自动解压(推荐)
只需在curl_setopt_array配置中新增CURLOPT_ENCODING参数即可,cURL会自动处理gzip/deflate等压缩格式,同时自动在请求头中添加对应的Accept-Encoding标识,无需手动编解码。
同时修正你截取响应体的错误逻辑:curl_getinfo返回的size_download是包含响应头的总下载字节数,不需要作为截取响应体的长度参数,直接从响应头结束位置截取到末尾即可。
修复后的完整代码如下:
$ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_HEADER => 1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0, CURLOPT_HTTPHEADER => $headers, CURLOPT_PROXY => $proxy, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_COOKIE => $sessionCookie, CURLOPT_VERBOSE => 0, // 新增配置:开启自动解压压缩响应 CURLOPT_ENCODING => '', ]); $response = curl_exec($ch); // 增加cURL执行错误判断 if(curl_errno($ch)) { throw new Exception('cURL请求错误: ' . curl_error($ch)); } $curl_info = curl_getinfo($ch); curl_close($ch); $header_size = $curl_info['header_size']; $headers = substr($response, 0, $header_size); // 修正截取逻辑:直接从header结束位置截到末尾 $body = substr($response, $header_size); // 增加json解析错误判断 $jsondata = json_decode($body,TRUE); if(json_last_error() !== JSON_ERROR_NONE) { throw new Exception('JSON解析错误: ' . json_last_error_msg()); }
方案2:手动解码gzip响应
如果不想通过cURL自动处理,也可以手动对压缩后的响应体做解码:
// 截取body之后增加解码逻辑 $header_size = $curl_info['header_size']; $headers = substr($response, 0, $header_size); $body = substr($response, $header_size); // 判断响应是否为gzip编码 if(stripos($headers, 'content-encoding: gzip') !== false) { $body = gzdecode($body); if($body === false) { throw new Exception('gzip解压失败'); } } $jsondata = json_decode($body,TRUE);
内容的提问来源于stack exchange,提问作者Gowtham
相关产品推荐
相关产品推荐

