HTTP之实体和编码

1. Content-Length: 实体的大小

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

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

1.1 检测截尾

客户端经过 Content-Length 来检测报文截尾。缓存

缓存代理服务器一般不会为没有显式 Content-Length 首部的 HTTP 主体作缓存,以此来减少缓存已截尾报文的风险。服务器

1.2 Content-Length 与持久链接

若是响应经过持久链接传送,就可能有另外一条 HTTP 响应紧随其后。客户端经过 Content-Length 首部就能够知道报文在何处结束,下一条报文从何处开始。由于链接是持久的,客户端没法依赖链接关闭来判别报文的结束。网络

有一种状况下,使用持久链接时能够没有 Content-Length 首部,即采用分块编码(chunked encoding)时。在分块编码的状况下,数据是分为一系列的块来发送的,每块都有大小说明。并发

1.3 内容编码

若是主体进行了内容编码,Content-Length 首部说明的就是编码后(encoded)的主体的字节长度,而不是未编码的原始主体的长度。app

2. 实体摘要

服务器使用 Content-MD5 首部发送对实体主体运行 MD5 算法的结果。只有产生响应的原始服务器能够计算并发送 Content-MD5 首部。中间代理和缓存不该当修改或添加这个首部,不然就会与验证端到端完整性的这个最终目的相冲突。Content-MD5 首部是在对内容作了全部须要的内容编码以后,尚未作任何传输编码以前,计算出来的。为了验证报文的完整性,客户端必须先进行传输编码的解码,而后计算所获得的未进行传输编码的实体主体的 MD5。ide

倘若一份文档使用 gzip 算法进行压缩,而后用分块编码发送,那么就对整个经 gzip 压缩的主体进行 MD5 计算。性能

3. 媒体类型和字符集

Content-Type 首部字段说明了实体主体的 MIME 类型。MIME 类型是标准化的名字,用以说明做为货物运载实体的基本媒体类型。优化

MIME 类型由一个主媒体类型(好比:text、image 或 audio 等)后面紧跟一条斜线以及一个子类型组成,子类型用于进一步描述媒体类型。

下列是一些 Content-Type 首部中经常使用的 MIME 类型。

  • text/html:实体主体是 HTML 文档
  • text/plain:实体主体是纯文本文档
  • image/gif:实体主体是 GIF 格式的图像
  • image/jpeg:实体主体是 JPEG 格式的图像
  • audio/x-wav:实体主体包含 WAV 格式的图像
  • model/vrml:实体主体是三维的 VRML 模型
  • application/vnd.ms-powerpoint:实体主体是 Microsoft PowerPoint 演示文档
  • multipart/byterange:实体主体有若干部分,每一个部分都包含了完整文档中不一样的字节范围
  • message/http:实体主体包含完整的 HTTTP 报文

Content-Type 首部说明的是原始实体主体的媒体类型。例如,若是实体通过内容编码的话,Content-Type 首部说明的还是编码以前的实体主体的类型。

3.1 文本的字符编码

Content-Type 首部还支持可选的参数来进一步说明内容的类型。如 charset(字符集)参数,它说明把实体中的比特转换为文本文件中的字符的方法:

Content-Type: text/html; charset=iso-8859-4

3.2 多部分媒体类型

MIME 中的 multipart(多部分)电子邮件报文中包含多个报文,它们合在一块儿做为单一的复杂报文发送。每一部分都是独立的,有各自的描述其内容的集;不一样的部分之间用分界字符串链接在一块儿。

HTTP 也支持多部分主体。不过,一般只用在下列两种情形之一:提交填写好的表格,或是做为承载若干文档片断的范围响应。

3.3 多部分表格提交

当提交填写的 HTTP 表格时,变长的文本字段和上传的对象都做为多部分主体里面独立的部分发送,这样表格中就能够填写各类不一样类型和长度的值。

HTTP 使用 Content-Type: multipart/form-data 或 Content-Type: multipart/mixed 这样的首部以及多部分主体来发送这种请求,示例以下:

Content-Type: multipart/form-data; boundary=[abcdefghijklnopqrstuvwxyz]

其中 boundary 参数说明了分割主体中不一样部分所用的字符串。

下例展现了 multipart/form-data 编码。假设有以下表格:

若用户在文本输入字段中键入了 Sally,并选择了文本文件 essayfile.txt,用户 Agent 代理可能会发回下面这样的数据:

Contet-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Sally
--AaB03x
Content-Disposition: form-data; name="files"; filename="essayfile.txt"
Content-Type: text/plain
..contents of essayfile.txt
--AaB03x

3.4 多部分范围响应

HTTP 对范围请求的响应也能够是多部分的。这样的响应中有 Content-Type: multipart/byteranges 首部和带有不一样范围的多部分主体。以下示例展现了对文档不一样范围的请求产生的响应:

4. 内容编码

HTTP 应用程序有时在发送以前须要对内容进行编码。

4.1 内容编码过程

  1. 网站服务器生成原始响应报文,其中有原始的 Content-Type 和 Content-Length 首部。
  2. 内容编码服务器建立编码后的报文。编码后的报文有一样的 Content-Type 但 Content-Length 可能不一样(如主体被压缩了)。内容编码服务器在编码后的报文中增长了 Content-Encoding 首部,这样接收的应用程序就能够进行解码了。
  3. 接收程序获得编码后的报文,进行解码,得到原始报文。

4.2 内容编码类型

HTTP 定义了一些标准的内容编码类型,并容许用扩展编码的形式增添更多的编码。由互联网号码分配机构(IANA)对各类编码进行标准化,它给每一个内容编码算法分配了惟一的代号。Content-Encoding 首部就用这些标准化的代号来讲明编码时使用的算法。

  • gzip:代表实体采用 GNU zip 编码
  • compress:代表实体采用 Unix 的文件压缩程序
  • deflate:代表实体是用 zlib 的格式压缩的
  • identity:代表没有对实体进行编码。当没有 Content-Encoding 首部时,就默认为这种状况

gzip、compress 以及 deflate 编码都是无损压缩算法,用于减小传输报文的大小,不会致使信息损失。

4.3 Accept-Encoding 首部

Accept-Encoding 字段包含了用逗号分隔的支持编码的列表:

  • Accept-Encoding: compress, gzip
  • Accept-Encoding:
  • Accept-Encoding: *
  • Accept-Encoding: compress;1=0.5, gzip;q=1.0
  • Accept-Encoding: gzip;q=1.0, identity; q=1.0, *;q=0

客户端能够给每种编码附带 Q(质量)值参数来讲明编码的优先级。Q 值的范围从 0.0 到 1.0,0.0 说明客户端不想接受所说明的编码,1.0 则代表最但愿使用的编码。"*" 表示 "任何其余方法"。

identity 编码代号只能在 Accept-Encoding 首部中出现,客户端用它来讲明相对于其余内容编码算法的优先级。

5. 传输编码和分块编码

使用传输编码是为了改变报文中的数据在网络上传输的方式。

5.1 Transfer-Encoding 首部

HTTP 协议中只定义了下面两个首部来描述和控制传输编码:

  • Transfer-Encoding:告知接收方为了可靠地传输报文,已经对其进行了何种编码。
  • TE:用在请求首部中,告知服务器可使用哪些传输编码扩展。

以下示例,请求使用了 TE 首部来告诉服务器它能够接受分块编码而且愿意接受附在分块编码的报文结尾上的拖鞋:

GET /new_products.html HTTP/1.1
Host: www.joes-hardware.com
User-Agent: Mozilla/4.61 [en] (WinNT; I)
TE: trailers, chunked
...

对它的响应中包含 Transfer-Encoding 首部,用该告诉接收方已经用分块编码对报文进行了传输编码:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Server: Apache/3.0
...

5.2 分块编码

分块编码把报文分割为若干个大小已知的块。块之间是紧挨着发送的,这样就不须要在发送以前知道整个报文的大小了。

注:分块编码是一种传输编码,所以是报文的属性,而不是主体的属性。多部分编码就是主体的属性,它和分块编码是彻底独立的。

1. 分块与持久链接

当使用持久链接时,在服务器写主体以前,必须知道它的大小并在 Content-Length 首部中发送。若是服务器动态建立内容,就可能在发送以前没法知道主体的长度。

分块编码解决了这种问题,只要容许服务器把主体逐块发送,说明每块的大小就能够了。

分块编码由起始的 HTTP 响应首部块开始,随后是一系列分块。每一个分块包含一个长度值和该分块的数据。长度值是十六进制形式并将 CRLF 与数据分隔开。分块中数据的大小以字节计算,不包括长度值与数据之间的 CRLF 序列以及分块结尾的 CRLF 序列。最后一个块的长度值为 0,表示"主体结束"。

2. 分块报文的拖挂

若客户端的 TE 首部中说明它能够接受拖挂的话,就能够在分块的报文最后加上拖挂。产生原始响应的服务器也能够在分块的报文最后加上拖挂。拖挂的内容是可选的元数据,客户端不必定须要理解和使用(客户端能够忽略并丢弃拖挂中的内容)。

拖挂中能够包含附带的首部字段,它们的值在报文开始的时候多是没法肯定的(如,必需要先生成主体的内容)。Content-MD5 首部就是一个能够在拖挂中发送的首部,由于在文档生成以前,很难算出它的 MD5。

除了 Transfer-Encoding、Trailer 以及 Content-Length 首部以外,其余 HTTP 首部均可以做为拖挂发送。

6. 范围请求

HTTP 容许客户端只请求文档的一部分,或者说某个范围。服务器能够经过在响应中包含 Accept-Rranges 首部的形式向客户端说明能够接受的范围请求。这个首部的值是计算范围的单位,一般是以字节计算的:

HTTP/1.1 200 OK
Date: Fri, 05 Nov 1999 22:35:15 GMT
Server: Apache/1.2.4
Accept-Ranges: bytes
...

7. 差别编码

差别编码是 HTTP 协议的一个扩展,它经过交换对象改变的部分而不是完整的对象来优化传输性能。

客户端在 If-None-Match 首部中使用的是它所持有页面版本的惟一标识,这个标识是服务器以前响应客户端时在 ETag 首部中发送的。

差别编码所用的首部:

  • ETag:文档每一个实例的惟一标识符。由服务器在响应中发送;客户端在后继请求的 If-Match 首部和 If-None-Match 首部中可使用它
  • If-None-Match:客户端发送的请求首部,当且仅当客户端的文档版本与服务器不一样时,才行服务器请求该文档
  • A-IM:客户端请求首部,说明能够接受的实例操控类型
  • IM:服务器响应首部,说明做用在响应上的实例操控的类型。当响应代码是 226 IM Used 时,会发送这个首部
  • Delta-Base:服务器响应首部,说明用于计算差别的基线文档的 ETag 值(应当与客户端请求中的 If-None-Match 首部里的 ETag 相同)

7.1 实例操控、差别生成器和差别应用器

客户端可使用 A-IM 首部说明能够接受的一些实例操控的类型。服务器在 IM 首部中说明使用的是何种实例操控。

在 IANA 注册的实例操控类型:

  • vcdiff:用 vcdiff 算法计算差别
  • diffe:用 Unix 系统的 diff-e 命令计算差别
  • gdiff:用 gdiff 算法计算差别
  • gzip:用 gzip 算法压缩
  • deflate:用 deflate 算法压缩
  • range:用在服务器的响应中,说明响应是针对范围选择获得的部份内容
  • identity:用在客户端请求中的 A-IM 首部中,说明客户端愿意接受恒等实例操控
相关文章
相关标签/搜索