ABNF范式:https://www.jianshu.com/p/fe82f22f09f6
回顾下ABNF范式对HTTP包体的描述
message-body = *OCTET
OCTET为8位数据
*OCTET为二进制流
HTTP是应用层协议,除了发送数据后,还得告诉上层应用这是什么数据(头部定义)
如何告诉是什么数据,参考了MIME规范
有时候为了节约带宽,在传输过程中还会压缩数据,所以还需要一个Encoding type告诉对方用了什么编码
content := " Content-Type " ":" type "/" subtype *(";" parameter)
type := discrete-type / composite-type discrete-type :="text" / "image" / "audio" / "video" / "application" / extention-tokencomposite-type := "message" / "multipart" / extension-token extension-token :=ietf-token / x-tokensubtype :=extension-token / iana-tokenparameter := attribute "=" value
客户端用 Accept 头告诉服务器希望接收什么样的数据,而服务器用 Content 头告诉客户端实际发送了什么样的数据


Accept-Encoding字段标记的是客户端支持的压缩格式,例如上面说的 gzip、deflate 等,同样也可以用“,”列出多个,服务器可以选择其中一种来压缩数据,实际使用的压缩格式放在响应头字段Content-Encoding里


同理语言:Accept-Language和Content-Language
编码:Accept-Charset和Content-Charset

我们将这些双方对消息包体的内容约束称为内容协商(还有质量因子q)
HTTP包体的传输方式
包体的传输方式分为两种
1.定长传输
这个很常见,即在发送HTTP消息时已经能够确定包体的长度
其中包体的长度我们在头部Content-Length中指明
Content-Length = 1*DIGIT
DIGIT为10进制
为什么要用10进制表示,因为这需要被我们肉眼所观察到

那么如果两者不一致会出现什么情况?即Content-length和包体实际长度不一致
我们实验测试一下
这里我用php的swoole搭建(需要安装最新swoole扩展)

再来回顾下ABNF对响应的定义
HTTP-message = status-line *(header-field CRLF)CRLF [message-body]
其中CRLF就相当于 \r\n

运行程序,分别浏览器访问和curl观察结果


当Content-length<实际长度



当Content-length>实际长度


2.不定长传输
后面不太理解,先记录别人的笔记
使用Transfer-Encoding头部指明使用的Chunk传输方式
含Transfer-Encoding头部后Content-Length头部应被忽略
优点:
基于长连接持续推送动态内容
压缩体积较大的包体时,不必完全压缩完(计算出头部)再发送,可以边发送边压缩
传递必须在包体传输完才能计算出的 Trailer 头部


表单提交时的包体格式
1.在表单提交时我们通常采用POST方法提交
2.在上传文件的表单中,我们通常会对表单的enctype添加选项
application/x-www.form-urlencode
抛出问题:为什么通常会进行以上约定?
关于enctype
enctype属性是在POST方法下对表单内容在请求包体中的提交方式
在w3c中有以下定义

默认地,表单数据会编码为 "application/x-www-form-urlencoded"
1.代码抓包测试
1.1.post和get的区别

GET提交:
在wireshark中表单数据以路由参数(明文)的形式显示

并且是在请求头中

POST:
在谷歌浏览器抓包面板中以包体明文的方式传输(点击view source展开)



总结:
在POST提交中,采用了application/x-www-form-urlencoded编码方式传输
并且该编码将参数以 & 方式连接
1.2.multipart/form-data的编码方式?
text/plain仅将空格转为+

先不上传文件对比

在Content-type中多了一堆看不懂的玩意儿
RFC中对Content-type为multipart/form-data时的描述
multipart直译为多部份
multipart/form-data即为一个包体中多个资源的表述
即表单中的每一个输入框都为独立的资源描述
RFC描述:
Contetn-Type: multipart/form-data;Boundray
其中Boundray为
boundray := 0*69<bchars> bcharsnospace;
·bchars := bcharsnospace / " "
·bcharsnospace := DIGIT / ALPHA / "" / "(" / ")" / "+" / "-" / "." / "/" /"=" / "?"
boundray不超过70个字符即

RFC对multipart包体格式的描述

其中第一个部分(preamble)和最后一个部分(epilogue)一般不使用,使用的时候接收端也会丢弃掉,所以不关注
1*encapsulation表示表单中每一个输入框都为一个encapsulation

最后结尾以close-delimiter即再加--

网友评论