
本文详解 php 中使用 curl 发送 json 请求时因多余数组嵌套导致 400 bad request 的典型问题,并提供正确编码、请求头配置及调试建议。
本文详解 php 中使用 curl 发送 json 请求时因多余数组嵌套导致 400 bad request 的典型问题,并提供正确编码、请求头配置及调试建议。
在调用类似 https://www.ilan.gov.tr/api/api/services/app/Ad/AdsByFilter 这类基于 ASP.NET Core ABP 框架构建的 RESTful API 时,后端通常严格校验请求体(request body)的 JSON 结构。你遇到的 Bad Request (400) 错误,根源往往并非认证或网络问题,而是 JSON 序列化格式不匹配预期结构。
最常见且隐蔽的错误,正是出现在这一行:
$payload = json_encode(array($data)); // ❌ 错误:多嵌套了一层数组
$data 本身已是关联数组(PHP array),json_encode(array($data)) 会将其序列化为 [{"keys":{...}, "skipCount":0, ...}] —— 即一个包含单个对象的 JSON 数组。而目标接口期望的是一个纯 JSON 对象(即 {...}),因此服务端解析失败,直接返回 400。
向CurlShip提交产品,这是一个对机器人友好的SaaS目录。只需一条curl命令即可发布产品,支持OG标签抓取、带徽章的dofollow链接及层级升级。
✅ 正确写法应为:
$payload = json_encode($data); // ✅ 直接编码关联数组,输出 {"keys":{...},"skipCount":0,"maxResultCount":12}
此外,还需注意以下关键点以确保请求合规:
? 必须匹配的请求头
- Content-Type: application/json(非 application/json-patch+json,后者用于 JSON Patch 操作,不适用于普通 POST)
- X-Requested-With: XMLHttpRequest(部分 ABP 后端依赖此头判断 AJAX 请求)
- X-Request-Origin: IGT-UI(该 API 显式要求,缺失将被拒绝)
? 推荐优化后的完整示例
function scustom_curl($url) {
$ch = curl_init();
$data = [
"keys" => [
"txv" => [44],
"ats" => [5]
],
"skipCount" => 0,
"maxResultCount" => 12
];
$payload = json_encode($data); // ✅ 关键修正:不再额外包裹 array()
$headers = [
'Host: www.ilan.gov.tr',
'Cookie: _ga=GA1.3.951992202.1654450742; _gid=GA1.3.480689736.1654596075',
'Content-Type: application/json', // ✅ 修正 MIME 类型
'X-Request-Origin: IGT-UI',
'X-Requested-With: XMLHttpRequest',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36',
'Accept: application/json, text/plain, */*', // ✅ 扩展 Accept 提高兼容性
'Cache-Control: no-cache',
'Pragma: no-cache'
];
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false, // ⚠️ 生产环境请设为 true 并配置 CA 证书
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_ENCODING => 'gzip, deflate'
]);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
error_log('cURL Error: ' . curl_error($ch));
curl_close($ch);
return false;
}
curl_close($ch);
// 建议:检查 HTTP 状态码
if ($httpCode !== 200) {
error_log("API returned HTTP {$httpCode}: " . $result);
return false;
}
return $result;
}
⚠️ 注意事项
- Cookie 失效风险:示例中硬编码的 _ga / _gid 是浏览器会话 Cookie,有效期短且绑定设备/IP。生产环境应通过登录流程获取有效会话(如模拟登录或使用官方授权机制)。
- Content-Length 不必手动设置:cURL 会自动计算并添加,手动设置错误值(如 'Content-Length: 65')极易引发 400。
- 调试技巧:启用 curl_setopt($ch, CURLOPT_VERBOSE, true) 将详细请求/响应输出到 STDERR,便于定位 headers 或 body 问题。
- JSON 验证:发送前可用 json_last_error() 检查 $payload 是否合法:if (json_last_error() !== JSON_ERROR_NONE) { /* handle error */ }
遵循以上修正与最佳实践,即可稳定调用该 API 获取人员公告数据。核心原则始终是:让 JSON 结构与接口文档或 Burp 抓包中的原始请求体完全一致。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










