HTTPQUERY
English

Content-Length

用法

Content-Length 头传达 HTTP 消息体的确切字节大小。客户端依赖该值判断响应是否已完整接收,从而使连接在 HTTP/1.1 的持久连接中可供复用。

当服务器发送一个已知消息体大小的响应时,Content-Length 头允许客户端分配恰当大小的内存,并在下载过程中显示准确的进度指示。声明的长度与实际消息体大小不一致,则表示传输被截断或已损坏。

该头与分块 Transfer-Encoding 互斥。当服务器以流式方式发送大小未知的响应时,分块编码会取代固定的内容长度。在 HTTP/2 与 HTTP/3 中,帧机制在协议层处理消息边界,但 Content-Length 仍可用于校验消息体大小。

该值是一个非负整数,表示消息体中的八位字节(字节)数量。

示例

服务器返回一个 3,495 字节的 JSON 响应。客户端在认定消息完整之前恰好读取 3,495 字节。

Content-Length: 3495

一个 POST 请求发送表单消息体。Content-Length 头告诉服务器请求体中应有多少字节。

POST /submit HTTP/1.1
Host: example.re
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

field=value&other=something

使用分块传输编码的响应会完全省略 Content-Length 头。此时 Transfer-Encoding 头优先。

Transfer-Encoding: chunked

故障排查

传输失败与连接错误常常可以追溯到错误或冲突的 Content-Length 值。

传输中断或下载不完整。客户端接收到的字节数少于 Content-Length 声明的数量,并报告响应被截断。常见原因:源站过早关闭连接、代理超时中断了传输,或服务器错误计算了消息体大小。运行 curl -v https://example.re/file,将 Content-Length 头的值与实际接收到的字节数(显示在传输摘要中)进行比较。不一致即可确认该问题。

分块编码与 Content-Length 同时出现。在同一响应中同时发送 Transfer-Encoding: chunked 与 Content-Length 违反了 HTTP 规范。当 Transfer-Encoding 存在时客户端必须忽略 Content-Length,但并非所有实现都遵守该规则。使用分块编码时应移除 Content-Length。在 nginx 中,当消息体大小未知时会自动应用分块编码,此时 nginx 会省略 Content-Length。若自定义应用代码或中间件同时设置了这两个头,则需要修正。

中间件修改消息体后 Content-Length 出错。注入内容(分析脚本、安全令牌、调试工具栏)的中间件会改变消息体大小却不更新 Content-Length。浏览器要么截断可见内容,要么一直等待永远不会到达的字节。应将 Content-Length 的计算移到所有消息体修改完成之后的最终阶段。在 Express.js 中,compression 中间件会自动处理这一点。在自定义环境中,应移除 Content-Length 转而依赖分块编码。

HEAD 响应携带错误的 Content-Length。HEAD 响应必须携带与对应 GET 响应相同的 Content-Length,但不带消息体。某些框架生成的 HEAD 响应 Content-Length 为 0 或完全省略该头。可通过比较 curl -I https://example.re/resource(HEAD)与 curl -s -o /dev/null -w ’%{size_download}’ https://example.re/resource(GET 消息体大小)来验证。数值不一致会破坏依赖 HEAD 判断资源大小的下载管理器和缓存代理。

使用 curl 诊断 Content-Length 问题。运行 curl -v https://example.re/resource,在详细输出中查看 Content-Length 头与传输字节数。Content-Length: N 一行显示声明的大小。末尾的 bytes received 显示实际传输量。加上 -o /dev/null 可丢弃消息体、专注于头部。对于压缩响应,请注意 Content-Length 反映的是压缩后的大小,而非原始大小。