HTTP学习笔记(二)
HTTP的数据类型与编码
数据类型
电子邮件可以发送 ASCII 码以外的任意数据,方案的名字叫做“多用途互联网邮件扩展”(Multipurpose Internet Mail Extensions),简称为 MIME。
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,即不透明的二进制数据。
编码
MIME type 还不够,因为 HTTP 在传输时为了节约带宽,有时候还会压缩数据,为了不要让浏览器继续“猜”,还需要有一个“Encoding type”,告诉数据是用的什么编码格式,这样对方才能正确解压缩,还原出原始的数据。
Encoding type 就少了很多,常用的只有下面三种:
- gzip:GNU zip 压缩格式,也是互联网上最流行的压缩格式;
- deflate:zlib(deflate)压缩格式,流行程度仅次于 gzip;
- br:一种专门为 HTTP 优化的新压缩算法(Brotli)。
数据类型使用的头字段
客户端用 Accept 头告诉服务器希望接收什么样的数据,而服务器用 Content 头告诉客户端实际发送了什么样的数据。
- Accept:Accept(请求字段) 字段标记的是客户端可理解的 MIME type,可以用“,”做分隔符列出多个类型,让服务器有更多的选择余地。
1 | Accept: text/html,application/xml,image/webp,image/png |
这就是告诉服务器:“我能够看懂 HTML、XML 的文本,还有 webp 和 png 的图片,请给我这四类格式的数据”。
Accept-Encoding:(请求字段)字段标记的是客户端支持的压缩格式,例如上面说的 gzip、deflate 等,同样也可以用“,”列出多个,服务器可以选择其中一种来压缩数据,实际使用的压缩格式放在响应头字段 Content-Encoding 里。
Content-Type:(通用字段)服务器会在响应报文里用头字段 Content-Type 告诉实体数据的真实类型
1 | Content-Type: text/html |
这样浏览器看到报文里的类型是“text/html”就知道是 HTML 文件,会调用排版引擎渲染出页面,看到“image/png”就知道是一个 PNG 文件,就会在页面上显示出图像。
*content-(通用字段)字段也可以用在请求报文里,说明请求体的数据类型。
- Content-Encoding:(通用字段)服务器使用的压缩格式。
- Content-Encoding(通用字段)和Accept-Encoding(请求字段)是可以省略的,如果请求报文里没有 Accept-Encoding 字段,就表示客户端不支持压缩数据;如果响应报文里没有 Content-Encoding 字段,就表示响应数据没有被压缩。
语言类型与编码
- Accept-Language:(请求字段)标记了客户端可理解的自然语言,也允许用“,”做分隔符列出多个类型
语言类型的子类型,与MIME TYPE不同,使用”-“作为分隔符,而MIME类型是”Type/subType”
1 | Accept-Language: zh-CN, zh, en |
- Content-Language:(通用字段)服务器告诉客户端实体数据使用的实际语言类型,或者客户端告诉服务器body语言类型。
1 | Content-Language: zh-CN |
- Accept-Charset:浏览器可接受的字符集。
响应头里却没有对应的 Content-Charset,而是在 Content-Type 字段的数据类型后面用“charset=xxx”来表示,这点需要特别注意。
1 | Accept-Charset: gbk, utf-8 |
不过现在的浏览器都支持多种字符集,通常不会发送 Accept-Charset,而服务器也不会发送 Content-Language,因为使用的语言完全可以由字符集推断出来,所以在请求头里一般只会有 Accept-Language 字段,响应头里只会有 Content-Type 字段。
内容协商的质量值
在 HTTP 协议里用 Accept、Accept-Encoding、Accept-Language 等请求头字段进行内容协商的时候,还可以用一种特殊的“q”参数表示权重来设定优先级,这里的“q”是“quality factor”的意思。
权重的最大值是 1,最小值是 0.01,默认值是 1,如果值是 0 就表示拒绝。具体的形式是在数据类型或语言代码后面加一个“;”,然后是“q=value”。
这里要提醒的是“;”的用法,在大多数编程语言里“;”的断句语气要强于“,”,而在 HTTP 的内容协商里却恰好反了过来,“;”的意义是小于“,”的。
1 | Accept: text/html,application/xml;q=0.9,*/*;q=0.8 |
它表示浏览器最希望使用的是 HTML 文件,权重是 1,其次是 XML 文件,权重是 0.9,最后是任意数据类型,权重是 0.8。服务器收到请求头后,就会计算权重,再根据自己的实际情况优先输出 HTML 或者 XML。
例题:
要使用 POST 方法向服务器提交一些 JSON 格式的数据,里面包含有中文,请求头应该是什么样子的呢
1 | POST / HTTP/1.1 |
说明:
- charset不同同时使用两种编码
- Content-Language表示的是body数据的语言,因为post带有body,所以要用Content-Language来告诉服务器,报文的body是什么。
- Accept-Language是请求头字段,只要是发请求就可以带。
- Content-Language是实体头字段,只要是有body就可以带。
对应关系:
