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

发送/接收JSON数据时触发406错误,伴随nghttp2回调失败报错求解决

406错误排查:PHP CURL请求返回406及nghttp2报错分析

我尝试了StackOverflow上的多种方案,但代码仍无法正常运行。为排查问题,编写了两个基础测试脚本send.php和receive.php,却依然触发406错误,不知原因所在。

send.php

$url = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . "://".$_SERVER['HTTP_HOST'].str_replace(realpath($_SERVER['DOCUMENT_ROOT']), '', realpath(__DIR__))."/receive.php"; 
$data = array(
    'first_name' => "Bart",
    'last_name' => "Simpson",
);

$return_data=json_encode($data);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, true); // Required for HTTP error codes to be reported via our call to curl_error($ch)
curl_setopt($ch, CURLOPT_POSTFIELDS, $return_data);
$resp = curl_exec($ch);
if (curl_errno($ch)) {
    $ch_error_msg = curl_error($ch);
    echo "ERROR:".$ch_error_msg;
    exit;
}
curl_close($ch);

$result = json_decode($resp);
echo "<pre>".var_export($result,true)."<pre>";

receive.php

$response = file_get_contents('php://input');
$data = json_decode($response, true);
$data_display = var_export($data, true); // Nice readable view of array

if (isset($data['first_name']) && $data['first_name']!="")
{
        http_response_code(200);
        header("Content-Type:application/json");
        $return_data["http_status_code"]="200";
        $return_data["http_status_desc"]="OK";
        echo json_encode($return_data);
        exit;
}
else
{
        http_response_code(400);
        header("Content-Type:application/json");
        $return_data["http_status_code"]="400";
        $return_data["http_status_desc"]="Required data not supplied";
        echo json_encode($return_data);
        exit;
}

为何会出现406错误?

更新内容

我在$resp = curl_exec($ch);之前添加了以下代码:

$stderrh=tmpfile();
curl_setopt_array($ch,array(CURLOPT_VERBOSE=>1,CURLOPT_STDERR=>$stderrh));
$result=curl_exec($ch);
rewind($stderrh);
$stderr=stream_get_contents($stderrh);
fclose($stderrh);
echo "<pre>".$stderr."</pre>";

现在看到额外报错信息:

process_pending_input: nghttp2_session_mem_recv() 返回 -902:用户回调函数执行失败


问题分析与解决建议

406错误本意为服务器无法生成符合请求Accept头要求的响应,但你的代码中已明确设置Accept: application/json,且receive.php也返回了application/json类型的响应,因此核心问题大概率不在内容类型匹配上。结合nghttp2的-902报错,问题指向HTTP/2协议兼容性,以下是具体排查和解决步骤:

  1. 强制curl使用HTTP/1.1协议
    在send.php的curl配置中添加一行,禁用HTTP/2:
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

HTTP/2对协议格式要求更严格,部分服务器或curl版本存在兼容性问题,降级到HTTP/1.1可快速验证是否为协议导致的错误。

  1. 检查服务器端Web配置
    如果使用Nginx等服务器,需确认:
  • HTTP/2是否仅在HTTPS下启用(多数服务器不支持明文HTTP/2)
  • 服务器日志(如Nginx的error.log)中是否有HTTP/2处理相关的错误
  • 服务器是否存在拦截请求的安全规则(如WAF),导致请求被判定为不符合格式
  1. 简化请求头
    尝试移除Accept头,仅保留必要的Content-Type:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

部分服务器对Accept头的格式有特殊要求,简化后可排除头信息导致的问题。

  1. 确保响应无多余输出
    HTTP/2对响应格式要求严格,receive.php中若存在空格、换行或BOM头,会导致协议解析失败。可在脚本开头添加ob_start();,结尾添加ob_end_flush();,或检查文件是否带有UTF-8 BOM。

内容的提问来源于stack exchange,提问作者G-J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:04:59