http是一个无状态的应用层请求/响应协议,其请求和响应消息都是由起始行、若干行头部(以空行表示结尾)和可选的数据部分,那么在进行http请求时,响应的数据部分长度该如何确定呢?
按照rfc7230的描述,按照以下顺序确定响应的数据部分长度:
1 存在Transfer-Encoding头部
1.1 存在chunked编码
因为标准规定如果存在chunked编码,那么chunked编码必须是Transfer-Encoding的最后一个编码,比如Transfer-Encoding: chunked或者Transfer-Encoding: gzip, chunked。此时数据部分长度按照chunked编码解释:chunked编码就是分块传输编码,数据是以一系列的的分块发送的,每个分块都有自己的长度标识符,其具体原理为:
- 每个分块的开头是一行16进制的整数,表示该分块接下来的数据长度,这个数字后面跟一个\r\n(即回车换行),在长度和\r\n之间可选的包含一些块扩展
- 在长度行之后是数据内容,数据结束后跟一个\r\n
- 传输结束后,会发送一个长度为0的分块,即0\r\n\r\n,在0\r\n和\r\n之间可选的包含一些尾部部分
chunked编码数据如下所示,包含3个长度分别为4、10、0的分块,
4;name=val\r\n
abcd\r\n
A\r\n
0123456789\r\n
0\r\n
header-field-name: header-filed-value\r\n
\r\n
什么时间会用到chunked编码呢?在以下这些情况可能会用到:
- 动态内容:一下子不能获取所有数据,比如流媒体传输,此时内容是逐步生成的。
- 大文件传输:使用chunked编码减少内存的使用,避免在内存中缓存整个文件。
- 长轮询:服务器保持连接打开,直到有数据需要发送。
1.2 不存在chunked编码
此时数据长度依靠服务端的连接断开来决定,连接断开前接受的数据都是有效数据。
2 不存在Transfer-Encoding头部,存在Content-Length头部
Content-Length头部的值是一个10进制整数,表示接下来的数据部分长度,如下所示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 20
{“code”:0, msg:”ok”}
3 不存在Transfer-Encoding头部,也不存在Content-Length头部
这种情况和前面存在Transfer-Encoding头部但不存在chunked编码一致即此时数据长度依靠服务端的连接断开来决定,连接断开前接受的数据都是有效数据。
响应和请求的数据部分长度的区别
前面描述的响应的是数据部分长度的确定,请求的数据部分长度的确定仅仅在最后一条不一样,即如果不存在Transfer-Encoding头部也不存在Content-Length头部,那么请求的数据部分长度为0,也就是说没有数据部分。