Body数据的内容协商
18888628835 opened this issue · 0 comments
Body数据的内容协商
数据类型与编码压缩
在 TCP/IP的协议栈中,传输数据基本上都是 Header+body 的格式,在传输过程中加上各自的头,它们并不关心 body 的数据是什么,只要把数据发送出去就可以了。
HTTP 并不是这样的,它是应用层的协议,数据到达之后的工作只完成了一半,它还必须告诉上层应用这是什么数据。
假设 HTTP 没有告知数据类型的功能,服务器把数据发送给浏览器,那么浏览器该怎么办?
它可以靠猜测,很多数据都是有固定格式的,所以通过代码检查数据的前几个字节也许就可以知道这是个 gif 或者是 mp3文件,但这样做无疑是低效的。
在 HTTP 诞生之前就已经有了针对这种问题的解决方法,这就是应用于电子邮件系统的 MIME(多用途互联网邮件扩展),他可以让电子邮件发送除了 ASCII 码外的数据。
HTTP 借鉴了一部分,用来标记 body 的数据类型,这就是我们经常听到的 MIME type
MIME 把数据分成八类,每个大类下继续分成子类,形式是 type/subtype
的字符串,这刚好可以纳入 HTTP 头字段中。
常用类别:
-
text:即文本格式的可读数据,我们常见的就是 text/html,表示超文本文档。此外还有text/plain 和 text/css。
-
image:图像文件,常见 image/gif、image/jpeg、image/png 等。
-
audio/video:音频和视频数据,例如 audio/mpeg、video/mp4等。
-
application:数据格式不固定,由上层应用程序解释。常见的有 application/json、application/JavaScript、application/pdf 等。如果实现不知道数据是什么,就会是 application/octet-stream,即不透明的二进制数据。
在 HTTP 传输时,为了节约带宽,有时候还会压缩数据,为了不让浏览器继续猜,还需要一个 Encoding type
,告诉数据是用什么编码格式,这样对方才能够正确解压缩,还原出原始的数据。
比起 MIME type
,Encoding type
就少很多,常用的就只有三种:
1.gzip:GNU zip 压缩格式,也是互联网流行的压缩格式。
2.deflate:zlib(deflate)压缩格式,流行程度仅次于 gzip
3.br:专门为 HTTP 优化的新压缩算法。
数据类型使用的头字段
有了 Encoding type
和 MIME type
,服务器和浏览器都可以知道body 数据的类型,那么能不能有一种字段,让双方互相协商,传递对方想要的数据呢?
有的。HTTP 定义了两个 Accept 请求头字段和两个 Content 实体头字段,用于客户端和服务器进行“内容协商”。
其中 Accept(接收)是浏览器告诉服务器希望接收什么样的数据,Content(内容)是服务器告诉浏览器传递过来的数据类型。
请求的头字段
POST /api/base/facade/file/file?action=upload HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
响应的头字段
HTTP/1.1 200 OK
content-type: application/json;charset=UTF-8
Content-Encoding: gzip
Accept字段标明客户端能够理解的MIME type
,上面*/*
的意思是都可以理解。多个格式之间使用,
分割。
Accept:text/html,application/json
Content-Type字段标明服务器给明的实体数据的类型。这样可以方便浏览器根据数据类型做出处理,比如是 text/html 就可以将它渲染出来。
Accept-Encoding和Content-Encoding分别是浏览器支持的解压缩格式和服务器的实际的压缩格式。
这个过程可以用收发快递来类比,比如我寄出去一个快递告诉我朋友我希望拿到 xxx 类型的东西(Accept),不过这东西我知道我朋友肯定会打包寄给我,所以我告诉他我支持用什么方式来拆包装(Accept-Encoding),我朋友收到后就返回给我某种类型(Content-Type),然后告诉我用指定的方式去拆包装(Content-Encoding)。
语言类型与编码
MIME type 和 Encoding type 解决了计算机理解 body 数据的问题,那么如何解决各国语言的问题呢?
HTTP 引入了语言类型与字符集。
所谓语言类型就是我们使用的汉语、英语、日语等,而语言可能也还有下属的地方语言,所以也是采用 type-subtype的形式,唯一的区别是语言类型用-
做分割。
例如:en 表示任意的英语,en-US 则表示美式英语,en-GB 表示英式英语,我们用的 zh-CN 则是汉语。
字符集是为什么而诞生呢?在计算机早期出现了很多语言环境下的字符集,比如英语下的 ASCII 码,汉语下的 GBK 等,为了做到字符的统一,Unicode 诞生了,后来随着互联网的普及,作为 Unicode的实现之一--utf-8大幅度流行,目前 utf-8也成为互联网上的标准字符集。
语言类型使用的头字段
HTTP 同样支持语言类型的 Accept 和 Content 实体头字段。
浏览器用的头字段为 Accept-Language,允许用,
分割。
Accept-Language:zh-CN,zh,en
上面的头字段意思是给我zh-CN 的汉语文字,没有的话就给我随便什么汉语,实在不行就给我英文吧。
字符集在请求短则使用 Accept-Charset。
Accept-Charset:utf-8,gbk
服务器使用的头字段为Content-Language,也就是服务器告诉浏览器我传的什么文字类型。
Content-Language:zh-CN
在服务器返回的字符集则是放在 Content-Type字段的后面,用‘charset=xxx’来表示。
Content-Type:text/html;charset=utf-8
现在的浏览器由于功能太强大,一般来说不会发送 Accept-Charset,因为它支持多种字符集,而服务器也不会发送 Content-Language,而是直接告诉浏览器用什么 charset 就行了。
小结
数据类型表示实体数据的内容是什么,使用 MIME type,相关的头部字段为 Accept 和 Content-Type
数据编码表示实体数据的压缩方式,相关的字段为 Accept-Encoding 和 Content-Encoding
语言类型表示实体数据的语言,相关的字段是 Accept-Language 和 Content-Language
字符集是实体数据的编码方式,相关的字段是 Accept-Charset 和 Content-Type