Swoole的rawContent读不到JSON数据是因为其默认将application/json视为可解析类型,自动解析后清空原始缓冲;需在server配置中禁用http_mime_types对JSON的声明,或改用getContent()获取原始体。

为什么 rawContent 读不到 POST 的 JSON 数据?
因为 Swoole 的 rawContent 只在请求体未被自动解析时才有效——而默认情况下,POST 请求若带 Content-Type: application/json,Swoole 会尝试解析并清空原始内容,导致 rawContent 返回空字符串或 null。这不是 bug,是设计行为。
- 仅当
Content-Type不匹配 Swoole 内置解析规则(如application/x-www-form-urlencoded、multipart/form-data)时,rawContent才保留原始字节 -
application/json被 Swoole 视为“可解析类型”,触发自动解析后清空缓冲,rawContent失效 - 即使你没调用
$request->post或$request->json,只要请求头含application/json,Swoole 就可能提前处理
怎么强制拿到原始 JSON 字符串?
绕过自动解析的唯一可靠方式:在请求到达前禁用 Swoole 对 JSON 类型的识别。这需要在 Server 启动时配置 http_parse_post 并显式排除 application/json:
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->set([
'http_parse_post' => true,
'http_mime_types' => [
// 只允许解析表单,不解析 JSON
'application/x-www-form-urlencoded' => 'form',
'multipart/form-data' => 'form',
// 不写 'application/json' => 'json' 这行!
],
]);- 必须设置
http_parse_post => true(否则连表单都解析不了,但 JSON 仍会被误判) -
http_mime_types中完全不声明application/json,Swoole 就不会触发 JSON 解析逻辑,rawContent才能保留原始数据 - 重启服务后,
$request->rawContent()就能拿到完整 JSON 字符串,例如{"name":"foo","id":123}
拿到 rawContent 后怎么安全转成数组?
别直接 json_decode($request->rawContent(), true) —— 原始内容可能为空、乱码或非 UTF-8,容易出错。
- 先检查长度:
if (strlen($request->rawContent()) === 0)直接返回错误 - 再验证编码:
mb_check_encoding($raw, 'UTF-8') === false时需转换或拒收 - 最后解析并检查错误:
$data = json_decode($raw, true); if (json_last_error() !== JSON_ERROR_NONE) { /* 处理解析失败 */ } - 注意:Swoole 4.8+ 默认启用
http_compression,若客户端发了Content-Encoding: gzip,rawContent是压缩后的二进制,需先解压(但 JSON 请求通常不压缩,可忽略)
有没有更省事的替代方案?
有,但代价是放弃原始字节控制权:用 $request->getContent()(Swoole 4.6+)代替 rawContent。它在所有情况下都返回原始请求体,不受 http_mime_types 影响。
-
$request->getContent()是更现代、更稳定的接口,推荐新项目直接用它 - 它不依赖
http_mime_types配置,也不受自动解析干扰,返回值和rawContent语义一致 - 旧版本(http_mime_types 方案,且必须严格配置
- 别混淆:
$request->getContent()≠$request->rawContent()在低版本——后者可能为空,前者才是真·原始体
真正麻烦的点在于:Swoole 没有“只禁用某一种 MIME 类型解析”的开关,必须全盘控制 http_mime_types;而很多人卡在没意识到 JSON 类型被默认接管,反复调试 rawContent 却始终为空。


















