HTTP常用请求头大揭秘

上面列出了报文的各种请求头、响应头、状态码,是不是感到特别晕呢。这节我们就专门挑一些最常用请求头,举例说明请求头对应支撑的HTTP功能。

4.1、数据类型、压缩编码,语言,内容协商和质量值

我们来看一个最基本的HTTP交互。

image-20200827004449052

其中,GET表示方法,就不多说了。

HostHost 请求头指明了请求将要发送到的服务器主机名和端口号。Host让虚拟主机托管成为了可能,也就是一个IP上提供多个Web服务。

协商

客户端先发送Accept、Accept-Encoding、Accept-Language请求头进行协商。其中:

Accept指明了客户端可理解的MIME type,用“,”做分隔符,列出多个类型;

Appcep-Encoding指明客户端可理解的压缩格式;

Accept-Languate指明客户端可理解的自然语言;

可以给每个协商项指定质量值q。质量值从0~1,1最高,表示最期望服务器采用该类型,0表示拒绝接受该类型。

协商结果

服务端会在响应头里面告知协商的结果:

Content-Type表示服务端实际采用的类型;

Content-Encoding表示服务端实际采用的压缩格式,如果相应报文没有该请求头,则代表服务端没有开启压缩;

Content-Language表示服务端实际采用的自然语言;

服务端是怎么协商的

服务端在客户端请求中,用了哪些请求头部信息进行协商的呢,这里需要用到Vary首部:

Vary: * Vary: <header-name>, <header-name>, ...

例如:

Vary: User-Agent

表示服务器依据 User-Agent 字段,决定发回了响应报文。此场景常见于:对于不同的终端,返回的内容是不同的,那么就需要用 User-Agnet进行区分以及缓存了。

更多协商信息:《HTTP权威指南》第17章 内容协商与转码

字符集

另外,客户端和服务端也可以协商字符集:

请求头:Accept-Charset;

响应头:没有单独的响应头,而是附加在Content-Type中:

Content-Type: text/html; charset=utf-8

协商请求响应头对应关系如下图:

image-20200829132909345

4.2、分块传输编码、范围请求和多段数据

分块传输响应头:Transfer-Encoding: chunked。

4.2.1、分块传输编码 Transfer-Encoding: chunked

一般情况下,我们请求后端,都可以拿到静态资源的完整Content-Length大小,一次性传输到客户端。

对于动态页面,也可以在后端一次性生成所有需要返回的内容,得到Content-Length大小,一次性传输到客户端。

但是想象以下场景:Content-Encoding为gzip,服务端进行压缩的时候,需要一块很大的字节数组进行压缩,最终得到整个数组的Content-Length。

举个例子:如下图:

image-20200829184027820

客户端需要向服务器请求获取一串葡萄,最期望拿到一串新疆葡萄,可以使用gzip编码。

最终客户端通过gzip,把葡萄压缩成了葡萄干,一次性传输给了客户端。客户端拿到了所有的葡萄干,解压回葡萄。

至于葡萄干注水还原回葡萄的技术有待大家研究实现,研究出来了可以分享给我,谢谢!

可以发现:服务端在压缩的过程中很占缓存,只能等压缩完成之后一次性传输,传输的内容庞大,瞬间占用网络,如果带宽不够,就会导致消息延迟

那么,这个时候,我们就可以使用分块传输来优化这个流程了:

我们可以将葡萄一颗一颗的压缩传输给客户端一颗,这样传输的时候就不用占用太多内存,传输也不会瞬时占用太多带宽了

image-20200829152932666

分块传输编码格式

下面我们通过一个具体的请求来说明分块传输编码的响应格式。

这里我们用OpenResty服务器,假设请求的服务端代码是这样的lua脚本:

ngx.header['Content-Type'] = 'text/plain;charset=utf-8' ngx.header['Transfer-Encoding'] = 'chunked' for i=1,10 do ngx.print('第' + i + '颗葡萄\n') ngx.flush(true) end

我们抓包来看看完整的TCP请求,图片比较大,感兴趣的同学放大查看:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyypfj.html