频道
bg

关于HTTP的Content-Length头

coding十月 19, 20171mins
HTTP

Content-Length 实体的大小H2

Content-Length首部指示出报文实体主体的字节大小,这个大小是包含了所有内容编码的。比如对文本文件进行了gzip压缩的话,Content-Length首部就是压缩后的大小,而不是原始大小。 另外Content-Length首部对于长连接是必不可少的,长连接代表在连接期间会有多个http请求响应在排队,而服务器不能够关闭连接,客户端只能通过Content-Length知道一条报文在哪里结束,下一条报文在哪里开始。 除非使用了分块编码Transfer-Encoding: chunked,否则响应头首部必须使用Content-Length首部。

传输编码和分块编码H2

分块编码把「报文」分割成若干个大小已知的块,块之间是紧挨着发送的,这样就不需要在发送之前知道整个报文的大小了。(也意味着不需要写回Content-Length首部了) 当使用持久连接时,在服务器写主体之前,必须知道它的大小并在Content-Length首部中发送。如果服务器动态创建内容,可能在发送之前无法知道主体大小,分块编码就是为了解决这种情况。服务器把主体逐块发送,说明每一块的大小。服务器再用大小为0的块作为结束块。 例如,下面一个分块传输的response

bash

HTTP/1.1 200 OK
Server: Tengine
Date: Thu, 04 Aug 2016 10:23:45 GMT
Content-Type: image/jpeg
Last-Modified: Mon, 11 Apr 2016 09:01:56 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Content-Encoding: gzip

分块编码的使用H3

结合Content-Encoding: gzip 使用的时候,Transfer-Encoding: chunked还是比较有用的。 不使用分块编码实现Content-Encoding: gzip 输出时,先把整个压缩后的数据写到一个很大的字节数组里(如 ByteArrayOutputStream),然后得到数组大小 -> Content-Length。 如果结合Transfer-Encoding: chunked使用,就不必申请一个很大的字节数组了,可以一块一块的输出,更科学,占用资源更少。 同样的客户端也没有直接的办法从相应头中知道的报文实体主体的大小,只能自己一个个统计chunk包的大小(或者同样的写到数组里,然后获取数组大小)。

在Chrome开发工具中查看响应的大小H2

如果单独请求GZIP压缩的资源文件查看网络,会出现一些比较奇怪的情况

  • SIZE会显示实际文件的大小而不是压缩过后的大小
  • Content Download的时间会把内容也页面加载的时间也算进去,即便下载早就已经完成

评论


新的评论

匹配您的Gravatar头像

Joen Yu

@2022 JoenYu, all rights reserved. Made with love.