Curl报错‘Failed sending HTTP request’:原因排查及代码问题咨询
关于Curl报错“Failed sending HTTP request”的排查与解决
问题背景
此前通过jQuery调用PHP文件从第三方API获取数据一直正常,修改登录方式后突然抛出Failed sending HTTP request错误。已确认API密钥正确,登录流程仅负责将密钥存入Session,与数据获取文件无其他关联。以下是相关代码及问题分析:
附:相关代码
Ajax请求代码
$.ajax({ method: "POST", url: "overview-left.php", success: function (data) { $(".leftContent").html(data); }, error: function (request, status, error) { $(".leftContent").html(error); }, });
PHP数据获取代码
<?php session_start(); $key = $_SESSION['apikey']; function getData($pageNum, $key) { $curl = curl_init(); $url = "https://api.website.com/v2/sales?page_number=" . $pageNum; curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, array( 'Authorization: Key ' . $key, 'Content-Type: application/json', 'User-Agent: Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion' )); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); $result = curl_exec($curl); if (!$result) { die("Curl error: " . curl_error($curl)); } $data = json_decode($result, true); $item = $data['sales']; return $item; } function showRecords($key) { $allrecords = array(); for ($i = 0; $i <= 8; $i++) { $record = getData($i, $key); $allrecords[] = $record; } foreach ($allrecords as $record) { foreach ($record as $row) { $sum[$row['product_title']] ??= 0; $sum[$row['product_title']] += $row['selling_price'] * $row['quantity']; } } $rowcount = 0; $showResults = 10; echo "<table>"; echo "<thead><tr><th class='image'></th><th class='wide-title'>Product Title</th><th class='number'>Revenue</th></tr></thead>"; arsort($sum); foreach ($sum as $key => $value) { $rowcount++; echo "<tr> <td class='centerCol'><img src='placeholder.png'/></td> <td>" . $key . "</td><td class='centerCol'>" . "R" . $value . "</td></tr>" . PHP_EOL; if ($rowcount == $showResults) { break; } } echo "</table>"; } showRecords($key); ?>
一、错误含义
Failed sending HTTP request是Curl的核心报错,说明Curl在尝试向目标API发起请求时彻底失败,请求甚至没能抵达API服务器(或被中间节点拦截),常见于网络连接失败、请求配置冲突、身份验证无效等场景。
二、Curl未发起请求的可能原因
- Session密钥失效/未正确读取:修改登录方式后,可能新流程未将API密钥写入
$_SESSION['apikey'],或Session的存储路径、生命周期配置变更,导致$key为空。无效的Authorization头会被API的前置拦截器直接拒绝,请求无法正常发送。 - Curl认证配置冲突:代码中设置了
CURLOPT_HTTPAUTH, CURLAUTH_BASIC(Basic认证),但API采用的是自定义Authorization: Key ...的密钥认证方式,两种认证逻辑冲突会导致Curl请求构造失败。 - User-Agent占位符无效:代码中的User-Agent是占位符(
platform; rv:geckoversion等),部分API会校验User-Agent的合法性,无效的User-Agent会被WAF(Web应用防火墙)拦截,请求无法发出。 - 服务器网络环境变更:修改登录方式可能伴随服务器配置调整(如防火墙规则、代理设置),导致服务器无法连接到API的域名或端口。
三、代码问题排查与优化
1. 增加Session密钥校验
在PHP开头添加校验,快速排除密钥为空的问题:
session_start(); if (!isset($_SESSION['apikey']) || empty(trim($_SESSION['apikey']))) { die("错误:API密钥未配置"); } $key = trim($_SESSION['apikey']);
2. 移除冲突的Basic认证配置
API采用自定义密钥认证,无需Basic认证,删除以下代码:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
3. 替换有效User-Agent
将占位符User-Agent改为真实有效的字符串,例如:
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36'
4. 完善Curl错误处理与资源释放
增加错误码排查,并手动关闭Curl资源避免内存泄漏:
function getData($pageNum, $key) { $curl = curl_init(); $url = "https://api.website.com/v2/sales?page_number=" . $pageNum; curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, array( 'Authorization: Key ' . $key, 'Content-Type: application/json', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' )); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 移除冲突的Basic认证配置 $result = curl_exec($curl); $errorCode = curl_errno($curl); curl_close($curl); // 释放Curl资源 if ($errorCode !== 0) { // 记录错误日志,而非直接终止程序 error_log("获取第{$pageNum}页数据失败:错误码{$errorCode},信息:" . curl_strerror($errorCode)); return array(); // 返回空数组,避免后续循环报错 } $data = json_decode($result, true); // 校验返回数据结构,防止解析失败 if (!isset($data['sales']) || !is_array($data['sales'])) { error_log("第{$pageNum}页数据格式异常:{$result}"); return array(); } return $data['sales']; }
5. 优化循环容错逻辑
原代码中任意一页请求失败就直接终止,改为跳过失败请求,保证页面能正常加载部分数据:
function showRecords($key) { $allrecords = array(); for ($i = 0; $i <= 8; $i++) { $record = getData($i, $key); if (!empty($record)) { // 仅添加有效数据 $allrecords[] = $record; } } // ... 后续逻辑保持不变 }
四、测试建议
- 直接在浏览器访问
overview-left.php,查看页面输出的具体错误信息(Ajax回调可能只返回部分错误)。 - 用Postman等工具模拟API请求,确认使用正确的密钥和User-Agent能正常获取数据,排除API本身的问题。
- 检查服务器的PHP错误日志,查看是否有Session相关的警告或错误。
内容的提问来源于stack exchange,提问作者crawlingdev
相关产品推荐
相关产品推荐

