数据结构论坛

注册

 

发新话题 回复该主题

HTTP常用请求头大揭秘 [复制链接]

1#

本文为《三万长文50+趣图带你领悟web编程的内功心法》第四个章节。

4、HTTP常用请求头大揭秘

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

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

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

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

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

协商

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

Accept指明了客户端可理解的MIMEtype,用“,”做分隔符,列出多个类型;Appcep-Encoding指明客户端可理解的压缩格式;Accept-Languate指明客户端可理解的自然语言;可以给每个协商项指定质量值q。质量值从0~1,1最高,表示最期望服务器采用该类型,0表示拒绝接受该类型。

协商结果

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

Content-Type表示服务端实际采用的类型;Content-Encoding表示服务端实际采用的压缩格式,如果相应报文没有该请求头,则代表服务端没有开启压缩;Content-Language表示服务端实际采用的自然语言;服务端是怎么协商的

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

VaryVary:header-name,header-name,...例如:

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

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

字符集

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

请求头:Accept-Charset;响应头:没有单独的响应头,而是附加在Content-Type中:Content-Type:text/html;charset=utf-8协商请求响应头对应关系如下图:

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

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

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

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

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

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

举个例子:如下图:

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

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

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

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

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

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

分块传输编码格式

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

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

ngx.header[Content-Type]=text/plain;charset=utf-8ngx.header[Transfer-Encoding]=chunkedfori=1,10dongx.print(第+i+颗葡萄\n)ngx.flush(true)end我们抓包来看看完整的TCP请求,图片比较大,感兴趣的同学放大查看:

分析下TCP包:

21~23:是TCP连接三次握手的过程;24:服务端通知客户端窗口大小变更;25:也就是第一个高亮的行,发起HTTP请求,尝试获取一串葡萄;27~41:服务端分块多次推送了一颗颗的葡萄给到客户端;43:最终在HTTP应用层,拿到了完整的一串葡萄,10个Datachunk对应10颗葡萄:

页面展示如下:

grape1grape2grape3grape4grape5grape6grape7grape8grape9grape10根据以上抓包的报文格式,可以得到最终的HTTP响应报文格式如下:

注意:分块传输和编码只在HTTP/1.1版本中提供。HTTP/2不支持分块传输,因为其本身提供的更加高级的流传输实现了类似的功能。

4.2.2、范围请求

范围请求响应头:Accept-Ranges:bytes,有这个响应头的,就表示当前响应的资源支持范围请求。

假设一个文件很大,我们想要获取其中的一部分,这个时候就可以使用范围请求了。范围请求常用语实现以下功能更:

看视频,拖到某一个时间点进行加载;下载工具中的多线程分段下载;下载工具中高端断点续传,如果网络不好,断开连接了,等到重新连接之后,可以继续获取剩余部分内容。范围请求头

确定了服务端支持范围请求之后,客户端在请求中使用Range请求头,指定要接收的范围即可,如:

--格式:bytes=x-y,xy表示偏移量,从0开始--请求获取前面11个字节Range:bytes=0-10--请求所有内容Range:bytes=10---获取文档最后10个字节Range:bytes=-10服务端响应

请求范围不合法,返回状态码:RangeNotSatisfiable;请求合法,返回状态码artialContent;响应头添加:Content-Range:bytesx-y/length,表示本次实际响应的范围

举个例子,我们请求IT宅首页,如下:

#执行以下请求:curl-i-HRange:bytes=0-15

分享 转发
TOP
发新话题 回复该主题