← 中文资源

简体中文版本

HTTP Content-Length 不匹配 — 响应被截断或多余

通过让框架自动设置该头、避免手动写入,并改用分块传输进行流式输出,修复 Content-Length 不匹配。

阅读英文原文

症状

本篇指南处理“HTTP Content-Length 不匹配 — 响应被截断或多余”。请从症状出发,按顺序执行诊断,在推进前确认每个假设;随后通过修复与验证步骤闭环。

可观察到的症状包括:

  • 客户端报 “premature end of Content-Length delimited message body”
  • 下载被截断或在即将完成时挂起
  • 处理器中手动设置 Content-Length 导致错误

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

curl -s -D - https://api.example.com/file -o out.bin && wc -c out.bin

实际大小与 Content-Length 头不同即证明不匹配。

步骤 2

grep -rn "Content-Length\|content-length" src/

手动设置长度是常见原因;应让框架自行计算。

常见诱因(按出现频率排序):

  • 手动设置的 Content-Length 与实际字节数不符
  • 处理器写入的字节多于或少于声明
  • 代理重新压缩或截断字节却保留原长度

根因

存在 Content-Length 时,客户端会恰好读取该字节数。若服务端或代理发送的数量不同,客户端会报过早结束,或等待永不到达的字节。

修复

让 HTTP 层依据实际响应体计算 Content-Length,避免手动设置;对长度未知的流采用分块传输(省略 Content-Length),使客户端读到终止块为止。

注意:压缩与手动 Content-Length 组合是非法的;压缩中间件应在压缩后设置长度或使用分块。

// Express: let the framework set Content-Length from the body
res.json(payload); // length computed automatically

// streaming unknown-length response: use chunked (no Content-Length)
res.setHeader('Transfer-Encoding', 'chunked');
res.setHeader('Content-Type', 'text/event-stream');
stream.pipe(res); // ends with a terminating chunk

验证

重新下载并确认字节数与头一致;验证完整文件的哈希正确。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。