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

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未发起请求的可能原因

  1. Session密钥失效/未正确读取:修改登录方式后,可能新流程未将API密钥写入$_SESSION['apikey'],或Session的存储路径、生命周期配置变更,导致$key为空。无效的Authorization头会被API的前置拦截器直接拒绝,请求无法正常发送。
  2. Curl认证配置冲突:代码中设置了CURLOPT_HTTPAUTH, CURLAUTH_BASIC(Basic认证),但API采用的是自定义Authorization: Key ...的密钥认证方式,两种认证逻辑冲突会导致Curl请求构造失败。
  3. User-Agent占位符无效:代码中的User-Agent是占位符(platform; rv:geckoversion等),部分API会校验User-Agent的合法性,无效的User-Agent会被WAF(Web应用防火墙)拦截,请求无法发出。
  4. 服务器网络环境变更:修改登录方式可能伴随服务器配置调整(如防火墙规则、代理设置),导致服务器无法连接到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;
        }
    }
    // ... 后续逻辑保持不变
}

四、测试建议

  1. 直接在浏览器访问overview-left.php,查看页面输出的具体错误信息(Ajax回调可能只返回部分错误)。
  2. 用Postman等工具模拟API请求,确认使用正确的密钥和User-Agent能正常获取数据,排除API本身的问题。
  3. 检查服务器的PHP错误日志,查看是否有Session相关的警告或错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:30:51