4月阅读周·HTTP权威指南:实体和编码之Content-Length:实体的大小篇

举报
叶一一 发表于 2025/04/22 09:44:44 2025/04/22
【摘要】 引言HTTP(Hypertext Transfer Protocol,超文本传输协议)是在万维网上进行通信时所使用的协议方案。HTTP有很多应用,但最著名的是用于Web浏览器和Web服务器之间的双工通信。《HTTP权威指南》一书将HTTP中一些互相关联且常被误解的规则梳理清楚,并编写了一系列基于各种主题的章节介绍HTTP各方面的特性。纵观全书,对HTTP“为什么”这样做进行了详细的解释,而不...

引言

HTTP(Hypertext Transfer Protocol,超文本传输协议)是在万维网上进行通信时所使用的协议方案。HTTP有很多应用,但最著名的是用于Web浏览器和Web服务器之间的双工通信。

《HTTP权威指南》一书将HTTP中一些互相关联且常被误解的规则梳理清楚,并编写了一系列基于各种主题的章节介绍HTTP各方面的特性。纵观全书,对HTTP“为什么”这样做进行了详细的解释,而不仅仅停留在它是“怎么做”的。此外,这本书还介绍了很多HTTP应用程序正常工作所必需且重要的非HTTP技术。

这本书主要包括以下内容:

  • 第一部分描述了Web的基础构件与HTTP的核心技术
  • 第二部分重点介绍了Web系统的结构构造块:HTTP服务器、代理、缓存、网关以及机器人应用程序。
  • 第三部分提供了一套用于追踪身份、增强安全性以及控制内容访问的技术和技巧。
  • 第四部分涵盖HTTP报文主体和Web标准,前者包含实际内容,后者描述并处理主体内容。
  • 第五部分介绍了发布和传播Web内容的技巧。
  • 第六部分是一些很有用的参考附录,以及相关技术的教程。

实体和编码

每天都有数以亿计的各种媒体对象经由HTTP传送,如图像、文本、影片以及软件程序等。只要你能叫出名字,HTTP就可以传送。HTTP还会确保它的报文被正确传送、识别、提取以及适当处理。

主要包括以下内容:

  • 作为HTTP数据的容器,HTTP报文实体有哪些格式和行为。
  • HTTP如何描述实体的主体大小,HTTP为确定大小制定了哪些规则。
  • 为了使客户端正确处理内容,使用了哪些实体首部来描述内容的格式、字母和语言。
  • 可逆的内容编码,发送方可以在发送之前用它来转换内容的数据格式,使其占用更小的空间,或者更安全。
  • 传输编码和分块编码。传输编码可以改变HTTP传输数据的方式,以改善某些类型内容的通信能力。分块编码是一种特殊的传输编码,它把数据切分为若干块,这样可以更可靠地传输长度未知的内容。
  • 标记、标签、时间以及校验和等一整套机制,帮助客户端获取所请求内容的最新版本。
  • 可用作内容版本号的验证码,网站应用可以通过它确保接收最新的内容。还有设计用来控制对象新鲜度的各种HTTP首部字段。
  • 范围,在恢复中断的传输方面很有用。
  • HTTP差异编码扩展,它使客户端只需要请求网页中和前一次相比有改变的部分。
  • 实体主体的校验和,可以用来检测经过若干代理之后,实体的内容是否发生了改变。

Content-Length:实体的大小

Content-Length首部指示出报文中实体主体的字节大小。这个大小是包含了所有内容编码的,比如,对文本文件进行了gzip压缩的话,Content-Length首部就是压缩后的大小,而不是原始大小。

检测截尾

HTTP的早期版本采用关闭连接的办法来划定报文的结束。但是,没有Content-Length的话,客户端无法区分到底是报文结束时正常的连接关闭,还是报文传输中由于服务器崩溃而导致的连接关闭。客户端需要通过Content-Length来检测报文截尾。报文截尾的问题对缓存代理服务器来说尤其严重。如果缓存服务器收到被截尾的报文却没有识别出截尾的话,它可能会存储不完整的内容并多次使用它来提供服务。缓存代理服务器通常不会为没有显式Content-Length首部的HTTP主体做缓存,以此来减小缓存已截尾报文的风险。

错误的Content-Length

错误的Content-Length比缺少Content-Length还要糟糕。因为某些早期的客户端和服务器在Content-Length计算上存在一些众所周知的错误,有些客户端、服务器以及代理中就包含了特别的算法,用来检测和纠正与有缺陷服务器的交互过程。HTTP/1.1规定用户Agent代理应该在接收且检测到无效长度时通知用户。

Content-Length与持久连接

Content-Length首部对于持久连接是必不可少的。如果响应通过持久连接传送,就可能有另一条HTTP响应紧随其后。客户端通过Content-Length首部就可以知道报文在何处结束,下一条报文从何处开始。因为连接是持久的,客户端无法依赖连接关闭来判别报文的结束。如果没有Content-Length首部,HTTP应用程序就不知道某个实体主体在哪里结束,下一条报文从哪里开始。

有一种情况下,使用持久连接时可以没有Content-Length首部,即采用分块编码(chunked encoding)时。在分块编码的情况下,数据是分为一系列的块来发送的,每块都有大小说明。哪怕服务器在生成首部的时候不知道整个实体的大小(通常是因为实体是动态生成的),仍然可以使用分块编码传输若干已知大小的块。

内容编码

HTTP允许对实体主体的内容进行编码,比如可以使之更安全或进行压缩以节省空间(本章稍后将详细解释压缩的问题)。如果主体进行了内容编码,Content-Length首部说明的就是编码后(encoded)的主体的字节长度,而不是未编码的原始主体的长度。

某些HTTP应用程序在这方面搞错了,发送的是数据编码之前的大小,这会导致严重的错误,尤其是用在持久连接上。不幸的是,HTTP/1.1规范中没有首部可以用来说明原始的、未编码的主体的长度,这就让客户端难以验证解码过程的完整性。

确定实体主体长度的规则

下面列出的规则说明了在若干不同的情况下如何正确计算主体的长度和结束位置。这些规则应当按顺序应用,谁先匹配就用谁。

(1)如果特定的HTTP报文类型中不允许带有主体,就忽略Content-Length首部,它是对(没有实际发送出来的)主体进行计算的。这种情况下,Content-Length首部是提示性的,并不说明实际的主体长度。(考虑不周的HTTP应用程序会认为有了Content-Length就有主体存在,这样就会出问题。)

最重要的例子就是HEAD响应。HEAD方法请求服务器发送等价的GET请求中会出现的首部,但不要包括主体。因为对GET的响应会带有Content-Length首部,所以HEAD响应里面也有;但和GET响应不同的是,HEAD响应中不会有主体。1XX、204以及304响应也可以有提示性的Content-Length首部,但是也都没有实体主体。那些规定不能带有实体主体的报文,不管带有什么首部字段,都必须在首部之后的第一个空行终止。

(2)如果报文中含有描述传输编码的Transfer-Encoding首部(不采用默认的HTTP“恒等”编码),那实体就应由一个称为“零字节块”(zero-byte chunk)的特殊模式结束,除非报文已经因连接关闭而结束。我们将在本章后面讨论传输编码和分块编码。

(3)如果报文中含有Content-Length首部(并且报文类型允许有实体主体),而且没有非恒等的Transfer-Encoding首部字段,那么Content-Length的值就是主体的长度。如果收到的报文中既有Content-Length首部字段又有非恒等的Transfer-Encoding首部字段,那就必须忽略Content-Length,因为传输编码会改变实体主体的表示和传输方式(因此可能就会改变传输的字节数)。

(4)如果报文使用了multipart/byteranges(多部分/字节范围)媒体类型,并且没有用Content-Length首部指出实体主体的长度,那么多部分报文中的每个部分都要说明它自己的大小。这种多部分类型是唯一的一种自定界的实体主体类型,因此除非发送方知道接收方可以解析它,否则就不能发送这种媒体类型。

(5)如果上面的规则都不匹配,实体就在连接关闭的时候结束。实际上,只有服务器可以使用连接关闭来指示报文的结束。客户端不能用关闭连接来指示客户端报文的结束,因为这样会使服务器无法发回响应。

为了和使用HTTP/1.0的应用程序兼容,任何带有实体主体的HTTP/1.1请求都必须带有正确的Content-Length首部字段(除非已经知道服务器兼容HTTP/1.1)。HTTP/1.1规范中建议对于带有主体但没有Content-Length首部的请求,服务器如果无法确定报文的长度,就应当发送400 Bad Request响应或411 Length Required响应,后一种情况表明服务器要求收到正确的Content-Length首部。

总结

除非使用了分块编码,否则Content-Length首部就是带有实体主体的报文必须使用的。使用Content-Length首部是为了能够检测出服务器崩溃而导致的报文截尾,并对共享持久连接的多个报文进行正确分段。


作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。