-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http 协议的结束符 #34
Labels
Comments
mark |
mark |
有关消息体长度的 RFC 链接:https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.3 其中完整说明了确定消息体长度,即确定消息结束的所有情况,除了 Transfer-Encoding 和 Content-Length 外,还有一些其他情况需要考虑。当然最为常见的情况是 chunked Transfer-Encoding, Content-Length,以及消息体为空的情况。🤖 |
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http 协议的结束符
突然想起很久之前一次面试,面试官问我,当请求头没有
content-length
时,怎么知道请求体结束了?http 的
header
和body
之间空行分割的,又因为每个头部项是以\r\n
作为结束符,所以,数据流中是以\r\n\r\n
来分割解析请求头(响应头)与请求体(响应体)的。如下图所示:那么怎么知道(请求体)响应体结束了呢? http 协议规定,响应头的字段
content-length
用来表示响应体长度大小,但是,有可能发送请求头时,并不能知道完整的响应体长度(比如当响应数据太大,服务端流式处理的情况),这时需要设置请求头Transfer-Encoding: chunked
,使用数据块的方式传输,数据块格式如下图所示:每个数据块分为两个部分:数据长度和数据内容,以
\r\n
分割,最后长度为 0 的数据块,内容为空行(\r\n
),表示没有数据再传输了,响应结束。需要注意的是,此时,content-length
不应该被设置,就算设置了,也会被忽略掉。回到最开始的那个问题,我当时对 http 协议不太清楚,回答不上来,那位面试官就告诉我,可以使用
\r\n\r\n
来判断,现在看来,他说的并不严谨。首先,http 协议并没有规定请求体(响应体)要以\r\n\r\n
作为结束符,其次,很重要的一点是,响应体(请求体)的内容是多种多样的,你没法做限制,当数据内容包含\r\n\r\n
时,显然解析出来的响应体就是不全的。当然,如果是自己实现 http 服务端的话,怎么兼容这种情况呢?
如果是短连接的话,比较简单,连接关闭就表示数据传输完成了。如果是长连接的话,一种不太优雅的方式就是使用超时机制,当读取超过一定时间,就认为数据已经传输完成。
总之,判断数据(块)结束最严谨的方式是计算长度,而不是使用结束符,但是,一般可控的场景下(双方约定),还是可以选择使用结束符来判断的,这样实现起来会更简洁。此时,为了防止内容中包含约定的结束符,导致数据内容被提前截断,客户端可以在发送数据时先对内容中的约定结束符进行编码。
扩展
因为服务端在解析请求头和请求体时,都需要依据以上协议,来读取完整数据。
Slow Headers
与Slow POST
两类 DDoS 慢速攻击正是利用了这个原理。The text was updated successfully, but these errors were encountered: