书里的「实体」指内容本身,「报文主体」指经过内容编码后实际传输的字节。 两者在压缩时不相等——这个术语已被 2014 年的新规范删掉。
上一节拆了报文四段。 这一节专门掰清楚「主体」这个词的两种含义,因为后面两节(内容编码、 分块传输)都建立在这个区分上。
一、书里的定义
按 RFC 2616 的说法:实体(entity)= 实体首部 + 实体主体,而报文主体是「实际传输的那段字节」。
不压缩时两者相等;
一旦用了 Content-Encoding: gzip,报文主体是压缩后的字节,
实体主体是解压后的内容——两者就差了一整个压缩比。
为什么要区分?因为校验、范围请求、内容协商全都针对「实体」算,而长度、分块却针对「报文主体」算。
混了就会算错。
二、实测:两个 MD5 不一样
Demo 里 2320 字节的内容压成 104 字节。
原始内容的 MD5 是 2db80300a9190fba0201f8aef3a2e027,
传输字节的 MD5 是 ddc8f7179478ba4c557f2c40105f9740。
两个 md5 完全不同。
如果客户端拿传输过来的字节直接算 MD5 去比对,永远对不上——必须先按 Content-Encoding 解码,
再校验。
这个顺序在 Content-MD5 这种首部上尤其重要(书里 6.6.6 节提到了它,
但没说清它算的是哪一层——答案是编码后的字节)。
三、2014 年之后这组词已经废了
RFC 7230 把 entity 整个概念删了,只留下 message body 和 payload。
现在说「实体」属于老派说法,工程里没人用。
所以读这本书要做一个转换:书里的「实体」大致等于现在说的「解码后的载荷」;
书里的「报文主体」就是「实际传的字节」。
这不是这本书的错——它写于 2013 年,引的是当时的规范。
但用今天的话跟人对齐时,最好直接说「压缩前/压缩后」,歧义最小。
四、动手 Demo:同一份内容,压缩前后两个 MD5
拿 2320 字节的 HTML 压一次,分别算原始字节与压缩字节的 MD5,看它们是不是同一份东西。
raw = BIG
gz = gzip.compress(raw, 9)
print(u'原始', len(raw), hashlib.md5(raw).hexdigest())
print(u'压缩后', len(gz), hashlib.md5(gz).hexdigest())
print(u'报文主体', len(gz), u'(=编码后的实体)')
实跑输出:
--------------------------------------------------------------------
报文主体不等于实体主体
--------------------------------------------------------------------
实体(原始内容) 2320 字节
它的 MD5 2db80300a9190fba0201f8aef3a2e027
内容编码之后 104 字节(4%)
传输字节的 MD5 778de6ea092d5fa7856a7f3fe10513b8
报文主体 104 字节(=编码后的实体)
两者相等吗 否,差 2216 字节
《图解HTTP》的说法 实体=报文主体经内容编码后剩下的部分
RFC 7230 之后的说法 报文主体直接就是载荷;实体这个词已从规范里删掉
这就是第三章最容易混的一对词。**书用的是 1999 年的 RFC 2616 术语**,
2014 年 RFC 7230 把 entity 整个概念删了,只留 message body。
实际工程里没人区分这两个词;要看的是 Content-Encoding 到底加没加。
Demo 里两个 MD5 不同,说明客户端**必须先用 Content-Encoding 解码**,
才能拿到能校验的原始内容——顺序搞反,校验永远失败。
实体(原始内容)2320 字节 → 内容编码之后 104 字节(4%)。
这个压缩比特别高,是因为样本里同一句话重复了四十遍——重复度越高,gzip 越猛,
真实页面一般压到两三成。
两者相等吗 否,差 2216 字节——这就是书里那个区分存在的全部理由。
顺手记一个易错点:Content-Length 报的是压缩后的字节数(104),不是 2320。
报错这个数,客户端会一直等剩下的 2216 字节。
30 秒实验
- 把
gzip.compress换成zlib.compress,看两个 MD5 变不变。 - 先算原始内容的 MD5 再 gzip 传,客户端解码后重算——这就是
Content-MD5的正确用法。 - 想一想:范围请求的
Range是在压缩前还是压缩后的字节上算?
常见误区
- 「报文主体就是正文」——它是「传输形态的正文」,压缩时不等于内容本身。
- 「
Content-Length是内容长度」——是传输字节数,压缩后算。 - 「实体这个词现在还在用」——2014 年已被规范删除,只是老书还在用。
自测三问(点开对答案)
1. 报文主体与实体主体的区别? —— 报文主体是实际传输的字节;实体主体是解码后的内容。压缩时两者不等。 2. `Content-Length` 报的是哪一个? —— 报文主体的长度,也就是压缩后的字节数。 3. 为什么校验必须先解码? —— 因为校验和通常是对原始内容算的,拿压缩字节去算必然对不上。概念分清了。下一节看最常用的一种内容编码:压缩。
- ☐ (本节完,下一节 3.3.2 压缩传输的内容编码)