一、前言
我们在日常的抓包过程中经常可以看到以Accept开头的请求首部,比如:Accept-Language 有一个q值,肯定有人好奇在HTTP规范中为什么要定义这个q值;还有在响应首部有一个名为Vary的首部,这个首部又有什么意义?如图所示:
 
二、内容协商
要讲清楚这两个问题,我们需要引入HTTP协议的内容协商概念:某一资源,服务器有多个版本,客户端告知服务器自己的偏好,服务器根据偏好选择合适的版本响应客户端的请求。内容协商技术通常有三种实现方案:
(1)客户端驱动
客户端发起请求,服务器发送可选项列表,客户端作出选择后在发送第二次请求。
优点:比较容易实现
缺点:增加了时延,至少要发送两次请求,第一次请求获取资源列表,第二次获取选择的副本。
(2)服务器驱动
服务器检查客户端的请求首部集并决定提供哪个版本的页面。
优点:比客户端驱动的协商要快。HTTP提供了q机制,允许服务器近似匹配,还提供了vary首部供服务器告知下游的设备(如代理服务器)如何对请求估值。
缺点:首部集不匹配,服务器要做猜测
(3)透明协商
某个中间设备(通常是缓存代理)代表客户端进行协商
优点:免除了web服务器的协商开销,比客户端驱动的协商要快。
缺点:HTTP并没有提供相应的规范
 
其中,服务器驱动的解决方案应用的较为广泛。
 
三、通用的内容协商首部
客户端发送Accept首部集发送用户的偏好信息,服务器发送实体首部集匹配客户端的Accept首部集:
Accept Content-type
Accept-Language Content-Language
Accept-Encoding Content-Encoding
 
四、q质量值的应用场景
假设客户端的Accept-Language指定的是西班牙语,但是服务端只有英语与法语版本,这个客户端希望在没有西班牙语的时候优先返回英语。这就意味着,我们需要一种HTTP机制更详细的描述偏好。这种机制就是质量值(q值)。示例如下:
Accept-Language: en;q=0.5, fr;q=0.0, nl;q=1.0, tr;q=0.0
这个首部表示:用户最愿意接受荷兰语(nl),英文也行(en),就是不愿意接受法语(fr)或者土耳其语(tr)
q值的范围从0.0~1.0(1.0优先级最高)
 
五、vary首部的应用场景
服务器的决策不是依据Accept首部集(常规的内容协商首部集),而是比如Accept-Encoding
假设整个请求过程是这样的:客户端 -> 代理服务器(具备缓存功能) ->web服务器。
第一个支持gzip压缩的客户端向中间代理服务器发送请求,代理服务器转发该请求,向web服务器拉取内容,拿到内容后代理服务器缓存该内容(由于请求首部有Accept-Encoding: gzip 所以内容会被压缩)。
第二个不支持gzip压缩的客户端也向中间代理服务器发送同一个请求,代理服务器发现该请求已经被缓存了,于是就把压缩后的内容响应给该客户端。悲剧了,因为该客户端根本不支持gzip压缩,也就没法解压。
 
六、Vary首部的工作原理
HTTP的Vary响应首部中列出了所有客户端请求首部,缓存服务器可以用这些首部来选择文档或者产生定制的内容。比如:若给客户端的响应内容取决于Accept-Encoding,Vary首部就必须包含Accept-Encoding。
当新的请求到达时,缓存服务器会根据内容协商首部集来寻找最佳匹配。但是在把文档提供给客户端之前,它必须检查web服务器有没有在已缓存响应中发生Vary首部。如果有,那么新请求中那些首部的值必须与旧的已缓存请求里相应的首部相同。因为web服务器可能会根据客户端请求的首部来改变响应,为了实现透明协商,缓存服务器必须为每个已缓存变体保存客户端请求首部和相应的服务器响应首部
 
简单的讲:
web服务器添加响应首部Vary: Accept-Encoding 告知代理服务器根据客户端的请求首部Accept-Encoding缓存不同的版本,这样下次客户端请求同一资源时,根据Accept-Encoding选择相应的缓存版本响应。
 
其实我们还可以禁用中间实体的缓存功能解决该问题:
web服务器设置响应首部: Cache-Control: private
 
通常添加Vary首部的解决方案比较通用,因为我们还是希望充分利用中间实体的缓存功能的。
 
七、参考资料
书籍:《HTTP权威指南》
 

HTTP协议的内容协商的更多相关文章

  1. HTTP协议之内容协商

    一个URL常常需要代表若干不同的资源.例如那种需要以多种语言提供其内容的网站站点.如果某个站点有说法语的和说英语的两种用户,它可能想用这两种语言提供网站站点信息.理想情况下,服务器应当向英语用户发送英 ...

  2. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  3. HandlerMethodArgumentResolver(三):基于消息转换器的参数处理器【享学Spring MVC】

    每篇一句 一个事实是:对于大多数技术,了解只需要一天,简单搞起来只需要一周.入门可能只需要一个月 前言 通过 前面两篇文章 的介绍,相信你对HandlerMethodArgumentResolver了 ...

  4. 看完这篇HTTP,跟面试官扯皮就没问题了

    我是一名程序员,我的主要编程语言是 Java,我更是一名 Web 开发人员,所以我必须要了解 HTTP,所以本篇文章就来带你从 HTTP 入门到进阶,看完让你有一种恍然大悟.醍醐灌顶的感觉. 最初在有 ...

  5. 51 张图助你彻底掌握 HTTP!

    前言 如果说 TCP/IP 协议是互联网通信的根基,那么 HTTP 就是其中当之无愧的王者,小到日常生活中的游戏,新闻,大到双十一秒杀等都能看到它的身影,据 NetCraft 统计,目前全球至少有 1 ...

  6. Web协议详解与抓包实战:HTTP1协议-内容协商是怎样进行的(8)

    一.内容协商的两种方式 每个 URI 指向的资源可以是任何事物,可以有多种不同的表述,例如一份文档可以有不同语言的翻译.不同的媒体格式.可以针对不同的浏览器提供不同的压缩编码等 二.Proactive ...

  7. 前端学HTTP之内容协商

    前面的话 一个URL常常需要代表若干不同的资源.例如那种需要以多种语言提供其内容的网站站点.如果某个站点有说法语的和说英语的两种用户,它可能想用这两种语言提供网站站点信息.理想情况下,服务器应当向英语 ...

  8. HTTP协议详解(转)

    转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...

  9. HTTP协议详解

    Author :Jeffrey 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...

随机推荐

  1. MongoDB学习笔记之Mongoose的使用

    http://blog.csdn.net/sinat_25127047/article/details/50560167

  2. Linux安装yum的痛苦路程(失败,慎入)

    1,在网上下载了一个yum 的 rpm文件(yum-3.2.29-81.el6.centos.noarch.rpm),我在 http://www.rpmfind.net/linux/rpm2html/ ...

  3. Python内置函数查询表——总结篇

    Python3.5版本中的68个内置函数,按顺序逐个进行了自认为详细的解析,现在是时候进行个总结了.为了方便记忆,将这些内置函数进行了如下分类:     数学运算(7个)     类型转换(24个) ...

  4. 二手前端入门React项目

    个人对ReactJS这门技术比较感兴趣,在基友的帮助下成功创建了一个React标准前端工程,过程中遇到了不少麻烦,今天作为笔记一般记录一下遇到的问题和解决方案. 基础环境 手头一台Mac 使用OSX系 ...

  5. dubbo服务器启动后报错端口被占用

    环境:maven工程,ssm框架,tomcat 情景:dubbo的服务注册方服务器启动 问题原因: 经过网络查找,结果是Root WebApplicationContext 启动了两次,第二次报错,d ...

  6. random 模块常用方法学习

    >>> import random#随机小数>>> random.random() # 大于0且小于1之间的小数0.7664338663654585>> ...

  7. python 全栈开发:str(字符串)常用方法操作 、for 有限循环以及if 循环

    str(字符串)常用方法操作: 首字母大写: s = 'mylovepython' s1 = s.capitalize() print(s1) 输出: Mylovepython 单行多字符串首字母大写 ...

  8. hiho#1449 重复旋律6 求长度为k的串最大次数 后缀自动机

    题目传送门 题目大意:求长度为k的串的最大次数,把k从1到length的所有答案全部输出. 思路: 这道题放在$SAM$里就是求长度$k$对应的所有$right$集中最大的大小. 我们以$aabab$ ...

  9. lightgbm调参方法

    gridsearchcv: https://www.cnblogs.com/bjwu/p/9307344.html gridsearchcv+lightgbm cv函数调参: https://www. ...

  10. js 数组随机排序

    仅用于个人学习记录 javascript 数组随机排序1.最简洁的方法:function randomsort(a, b) {    return Math.random()>.5 ? -1 : ...