发送/接收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协议兼容性,以下是具体排查和解决步骤:
- 强制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可快速验证是否为协议导致的错误。
- 检查服务器端Web配置
如果使用Nginx等服务器,需确认:
- HTTP/2是否仅在HTTPS下启用(多数服务器不支持明文HTTP/2)
- 服务器日志(如Nginx的
error.log)中是否有HTTP/2处理相关的错误 - 服务器是否存在拦截请求的安全规则(如WAF),导致请求被判定为不符合格式
- 简化请求头
尝试移除Accept头,仅保留必要的Content-Type:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
部分服务器对Accept头的格式有特殊要求,简化后可排除头信息导致的问题。
- 确保响应无多余输出
HTTP/2对响应格式要求严格,receive.php中若存在空格、换行或BOM头,会导致协议解析失败。可在脚本开头添加ob_start();,结尾添加ob_end_flush();,或检查文件是否带有UTF-8 BOM。
内容的提问来源于stack exchange,提问作者G-J
相关产品推荐
相关产品推荐

