如何解决 cURL 发送大体积 JSON 数据时返回 404 的问题

发布时间 - 2025-12-26 00:00:00    点击率:

当使用 curl 向 php 后端发送较大 json 字符串时,若直接以字符串形式传入 `curlopt_postfields`,apache 可能因请求体解析异常(如误判为非标准 post)而返回 404;正确做法是将 json 封装为关联数组键值对,并确保 content-type 与服务端接收逻辑一致。

在 Zend Server 2019.7(PHP 7.3 + Apache 2.4)环境中,你遇到的「小数据正常、大数据返回 404」现象,并非由 post_max_size 或 max_input_vars 等常见配置限制导致,而根本原因是 cURL 的 CURLOPT_POSTFIELDS 行为机制被 Apache/Zend Server 误解为“非标准表单提交”,从而触发路由或模块层面的 404 响应

? 问题根源解析

当你写:

curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data); // $json_data 是纯 JSON 字符串

cURL 会以 Content-Type: application/x-www-form-urlencoded(默认)发送请求 —— 即使你手动设置了 'Content-Type: application/json' 头,PHP 的 $_POST 超全局变量仍无法自动解析该 JSON 字符串,且某些服务器环境(尤其是 Zend Server 的请求过滤模块)会对无 name=value 结构的原始 POST body 做异常处理,甚至直接拒绝路由到目标脚本(如 recon.php),最终返回 404。

✅ 注意:404 并非来自 PHP 应用层(如文件不存在),而是 Apache/Zend Server 在请求预处理阶段因无法识别有效 POST 格式而中断了请求分发。

✅ 正确解决方案:封装为表单键值对 + 显式声明 Content-Type

将 JSON 字符串作为某个字段的值,通过数组方式提交,强制 cURL 使用 multipart/form-data 或保持 x-www-form-urlencoded 但结构合规:

$json_data = '{ "Recon": [ /* ... large JSON array ... */ ] }';

$url = 'http://192.168.1.100/projectname/recon.php';

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);

// ✅ 关键修复:将 JSON 作为数组字段值(而非裸字符串)
curl_setopt($ch, CURLOPT_POSTFIELDS, ['json_payload' => $json_data]);

// ✅ 必须显式声明 Content-Type(否则 Apache 可能忽略)
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: application/json'
]);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

$result = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "HTTP Code: $http_code\n";
echo $result;

? 服务端 recon.php 需同步适配

由于你已改用表单字段提交(json_payload),服务端不能再依赖 file_get_contents('php://input')(此时为空),而应从 $_POST 中读取并解码:

// recon.php
if (isset($_POST['json_payload'])) {
    $raw_json = $_POST['json_payload'];
    $data = json_decode($raw_json, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        http_response_code(400);
        echo json_encode(['error' => 'Invalid JSON']);
        exit;
    }

    // ✅ 正常处理 $data['Recon']...
    echo json_encode(['status' => 'success', 'count' => count($data['Recon'])]);
} else {
    http_response_code(400);
    echo json_encode(['error' => 'Missing json_payload']);
}

⚠️ 补充注意事项

  • 不要混淆 application/json 与表单提交:若坚持用 php://input 接收原始 JSON,则必须确保 CURLOPT_POSTFIELDS 传字符串 + Content-Type: application/json,且 Apache 的 mod_security、mod_proxy 或 Zend Server 的 Web Application Firewall(WAF)未拦截非常规 Content-Type 请求 —— 这在 Zend Server 中尤为常见。

  • 验证实际请求头:用 curl -v 或 Wireshark 抓包确认真实发出的 Content-Type 和 body 结构。

  • 检查 Zend Server 特定限制:进入 Zend Server Admin UI → Server ConfigPHP Settings,确认 suhosin.post.max_name_length、suhosin.request.max_value_length(如有启用 Suhosin)未截断长字段名或值。

  • 替代方案(推荐用于纯 API 场景):如需真正 RESTful 设计,建议统一使用 file_get_contents('php://input') + 原始 JSON 提交,并在 Apache 配置中显式允许:

    # 在虚拟主机或 .htaccess 中
    
        RewriteEngine On
        # 确保 JSON 请求不被重写规则误判
        RewriteCond %{CONTENT_TYPE} application/json
        RewriteRule .* - [E=HTTP_CONTENT_TYPE:application/json]
    

通过将 JSON 封装为 CURLOPT_POSTFIELDS 数组字段,既规避了 Apache 对裸 JSON body 的兼容性陷阱,又保持了向后兼容性与调试便利性 —— 这是 Zend Server 等企业级 PHP 环境中处理大体积 JSON POST 的稳健实践。


# php  # js  # json  # apache  # 大数据  # app  # access  # ssl  # 后端  # curl  # proxy  # 路由  # 表单提交  # restful  # 关联数组  # 封装 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: html5的keygen标签为什么废弃_替代方案说明【解答】  制作旅游网站html,怎样注册旅游网站?  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  什么是javascript作用域_全局和局部作用域有什么区别?  javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】  网站制作壁纸教程视频,电脑壁纸网站?  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  网站页面设计需要考虑到这些问题  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  EditPlus中的正则表达式 实战(4)  javascript基本数据类型及类型检测常用方法小结  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  创业网站制作流程,创业网站可靠吗?  JavaScript Ajax实现异步通信  详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南  Laravel如何使用.env文件管理环境变量?(最佳实践)  微信公众帐号开发教程之图文消息全攻略  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  如何用JavaScript实现文本编辑器_光标和选区怎么处理  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  教你用AI将一段旋律扩展成一首完整的曲子  微信小程序 闭包写法详细介绍  新三国志曹操传主线渭水交兵攻略  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  网站建设要注意的标准 促进网站用户好感度!  Laravel如何使用Vite进行前端资源打包?(配置示例)  如何构建满足综合性能需求的优质建站方案?  Laravel事件监听器怎么写_Laravel Event和Listener使用教程  Thinkphp 中 distinct 的用法解析  大学网站设计制作软件有哪些,如何将网站制作成自己app?  Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南  谷歌Google入口永久地址_Google搜索引擎官网首页永久入口  Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析  如何用PHP快速搭建CMS系统?  Android中AutoCompleteTextView自动提示  Laravel如何生成API文档?(Swagger/OpenAPI教程)  香港网站服务器数量如何影响SEO优化效果?  简历在线制作网站免费版,如何创建个人简历?  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  iOS正则表达式验证手机号、邮箱、身份证号等  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  JS经典正则表达式笔试题汇总  Laravel如何使用Telescope进行调试?(安装和使用教程)  百度浏览器如何管理插件 百度浏览器插件管理方法  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  高端智能建站公司优选:品牌定制与SEO优化一站式服务  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  详解CentOS6.5 安装 MySQL5.1.71的方法  Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件