Transfer-Encoding
在http1.1引入了 Transfer-Encoding 这个head
Transfer-Encoding: chunked
我们知道Content-Length 表明http的消息体的传输长度(不是消息体的原来长度)
在http1.1中,当服务器不明确的消息的长度是多少的时候,可以使用 Transfer-Encoding: chunked (表明服务器采用分块) 来代替Content-Length
根据协议描述,当出现Transfer-Encoding: chunked的时候Content-Length不应该出现
当Transfer-Encoding: chunked没有的时候必须出现Content-Length
在使用Transfer-Encoding: chunked的时候 还需要使用Connection: keep-alive模式
具体chunked是怎么编码的,请看下面
HTTP头\r\n (Length。 "Transfer-Encoding: chunked"是这样编码的:HTTP头\r\n (0D 0A)\r\n --连续的两个\r\n之后就是HTTP体了16进制值代表的数据长度\r\n上面所指的数据长度\r\n --每段数据结束后,以\r\n标识16进制代表的第二段数据
\r\nXX长度的数据\r\n………… (反复通过这样的方式表示每次传输的数据长度)0 --数据结束部分用0表示,然后是连续的两个\r\n\r\n\r\n
如果response没有设置Transfer-Encoding: chunked 也没有 Content-Length,那么客户端会等到服务器断掉tcp连接才认为数据传送完,这种情况下,无法区分是由于网络问题导致的还是由于response传输成功完成。
Transfer-Encoding: gzip, chunked
表明内容是经过gzip压缩的然后chunked,所以chunked必须放在最后。
但是感觉基本上会使用Content-Encoding:gzip 不使用Transfer-Encoding: gzip.
客户端可以收到部分chunk就开始进行解析,这样会用户体验好一些,所以服务器进行chunk划分的时候也是有一些技巧的
另外科普了一下:
Request中
Accept-Encoding: gzip, deflate, sdch 表明客户端可以接受的Encoding方法
Response中
Content-Encoding:gzip 表明服务器使用的Encoding方法
TE 和 Trailer
TE head表明客户端所支持Transfer-Ecoding方式,以及客户端是否愿意接受trailer fields 在一个chunked transfer ecoding中
注:chunked方式默认支持,不能在TE中声明
TE = #t-codings
t-codings = "trailers" / ( transfer-coding [ t-ranking ] )t-ranking = OWS ";" OWS "q=" rankrank = ( "0" [ "." 0*3DIGIT ] )/ ( "1" [ "." 0*3("0") ] )Three examples of TE use are below.TE: deflateTE:TE: trailers, deflate;q=0.5
trailers表明愿意接受trailer fields在chunked中
q=0.5表示愿意接受deflate的程度。 q的范围 0.0<1
The rank value is a real number in the range 0
through 1, where 0.001 is the least preferred and 1 is the mostpreferred; a value of 0 means "not acceptable".
Trailer:
当发送者期望在chunked的数据中发送trailer的时候,首先需要在消息的head中增加一个“Trailer = 1#field-name” 表明消息中有trailer以及是什么trailer. 这样在某种意义上可以保证数据的完整性
然后trailer会在chunked的结束部分出现。格式如下。
Chunked-Body = *chunk //0至多个chunk
last-chunk //最后一个chunk
trailer //尾部
CRLF //结束标记符
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
没有找到带trailer的实例,下面是自己的举例:
HTTP头
Trailer: sometrailer
Transfer-Encoding: Chunked
\r\n (0D 0A)
\r\n --连续的两个\r\n之后就是HTTP体了16进制值代表的数据长度\r\n上面所指的数据长度\r\n --每段数据结束后,以\r\n标识16进制代表的第二段数据
\r\nXX长度的数据\r\n………… (反复通过这样的方式表示每次传输的数据长度)0 --数据结束部分用0表示,然后是连续的两个\r\n\r\nsometrailer: trailerdata
\r\n