HTTP协议中的Content-Encoding

主要内容

    1.Content-Encoding是什么
    2.内容编码格式gzip和deflate

Content-Encoding是什么

Accept-Encoding和Content-Encoding是HTTP中用来对采用哪种编码格式传输正文进行协定的一对头部字段。

工作原理如下:

    1.首先浏览器(也就是客户端)发送请求时,通过Accept-Encoding带上自己支持的内容编码格式列表;

    2.服务端在接收到请求后,从中挑选出一种用来对响应信息进行编码,并通过Content-Encoding来说明服务端选定的编码信息

    3.浏览器在拿到响应正文后,依据Content-Encoding进行解压。

                服务端也可以返回未压缩的正文,但这种情况不允许返回Content-Encoding

内容编码的目的是优化传输内容的大小,通俗地讲就是尽心压缩。一般经过gzip压缩的文本响应,只要原始大小的1/4(这个数据我现在还不确定)。对于文本类响应是否开启了内容压缩,使我们做性能优化时首先要检查的重要项目;而对于JPG/PNG这类本身已经高度压缩过的二进制文件,不推介开启内容压缩,效果几乎微乎其微,还浪费cpu

内容的编码针对的只是传输正文。在HTTP/1中,头部始终是以ASCII文本传输,没有经过任何压缩。不过这个问题在HTTP/2中已经解决,详见HTTP/2 头部压缩技术介绍

内容编码使用特别广泛,理解起来也特别简单,但是要注意的是不要把它与HTTP中的另外一个概念:传输编码Transfer-Encoding搞混即可。

内容编码格式gzip和deflate

开始之前,先来介绍三种数据压缩格式:

  • DEFLATE,是一种使用Lempel-Ziv压缩算法(LZ77)和哈夫曼编码的数据压缩格式。定义了RFC 1951 : DEFLATE Compressed Data Format Specification;
  • ZLIB,是一种使用DEFLATE的数据压缩格式。定义于RFC 1950 : ZLIB Compressed Data Format Specification;
  • GZIP,是一种使用DEFLATE的文件格式。定义于RFC 1952 : GZIP file format specification

在HTTP/1.1的初始规范RFC 2616的[3.5 Content Codings],这一节中,这样定义了Content-Encoding中的gzip和deflate:

  •     gzip,一种由文件压缩程序[Gzip,GUN zip]产生的编码格式,描述于[DEFLATE]压缩机制是一种具有32位CRC的Lempel-Ziv编码(LZ77);
  •     deflate,由定义于RFC 1950的[ZLIB]编码格式与RFC 1951中描述的[DEFLATE]压缩机制组合而成的产物;

RFC 2616对Content-Encoding中的gzip的定义很清晰,它就是指在RFC 1952中定义的GZIP编码格式;但对deflate的定义含糊不清,实际上它值的是RFC 1950中定义的ZLIB编码格式,但deflate这个名字特别容易误会。

在Zlib库的官方网站,有这么一条FAQ:What’s the difference between the “gzip” and “deflate” HTTP 1.1 encodings? 就是在讨论HTTP/1.1对deflate的错误命名:

  Q:在HTTP/1.1的Content-Encoding中,gzip和deflate的区别是什么?

  A:gzip是指GZIP格式,deflate是指ZLIB格式。HTTP/1.1的作者或许应该将后者称之为zlib,从而避免与原始的 DEFLATE 数据格式产生混淆。虽然 HTTP/1.1 RFC 2016 正确指出,Content-Encoding 中的 deflate 就是 RFC 1950 描述的 ZLIB,但仍然有报告显示部分服务器及浏览器错误地生成或期望收到原始的 DEFLATE 格式,特别是微软。所以虽然使用 ZLIB 更为高效(实际上这正是 ZLIB 的设计目标),但使用 GZIP 格式可能更为可靠,这一切都是因为 HTTP/1.1 的作者不幸地选择了错误的命名。

结论:在 HTTP/1.1 的 Content-Encoding 中,请使用 gzip。

在 HTTP/1.1 的修订版 RFC 7230 的 4.2 Compression Codings 这一节中,彻底明确了 deflate 的含义,对 gzip 也做了补充:

  • deflate,包含「使用 Lempel-Ziv 压缩算法(LZ77)和哈夫曼编码的 DEFLATE 压缩数据流(RFC 1951)」的 ZLIB 数据格式(RFC 1950)。

    注:一些不符合规范的实现会发送没有经过 ZLIB 包装的 DEFLATE 压缩数据;

  • gzip,具有 32 位循环冗余检查(CRC)的 LZ77 编码,通常由 Gzip 文件压缩程序(RFC 1952)产生。接受方应该将 x-gzip 视为 gzip;

总结一下,HTTP标准中定义的Content-Encoding:deflate,实际上指的是ZLIB编码(RFC 1950).但由于RFC2616中含糊不清的定义,导致IE错误地实现为只接受原始DEFLATE(rfc 1951)。为空兼容IE,我们只能使用Content-Encoding:gzip进行内容编码,他指的是GZIP编码(RFC 1952)

其实上,ZLIB 和 DEFLATE 的差别很小:ZLIB 数据去掉 2 字节的 ZLIB 头,再忽略最后 4 字节的校验和,就变成了 DEFLATE 数据。

在 Fiddler 增加以下处理,就可以让 IE 支持标准的 Content-Encoding: deflate(ZLIB 编码):

if ((compressedData.Length > 2) &&
   ((compressedData[0] & 0xF) == 0x8) && //Low 4-bits must be 8
   ((compressedData[0] & 0x80) == 0) && //High-bit must be clear
   ((((compressedData[0] << 8) + compressedData[1]) % 31) == 0))
            //Validate checksum
{
    Debug.Write("Fiddler: Ignoring RFC1950 Header bytes for DEFLATE");
    iStartOffset = 2;
}

由于其他浏览器也能解析原始DEFLATE,所以有些WEB应用干脆为了迁就IE直接输出原始DEFLATE。

转载:https://imququ/post/content-encoding-header-in-http.html

 

 

 

 


 

 

 

 

更多推荐

HTTP协议中的Content-Encoding