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

HTTP提供了内容协商方法,允许客户端和服务器作这样的决定。通过这些方法,单一的URL就可以代表不同的资源(比如,同一个网站页面的法语版和英语版),这些不同的版本称为变体。本文将详细介绍内容协商。

一、概述

我们在日常的抓包过程中经常可以看到以Accept开头的请求首部,比如:Accept-Language 有一个q值,肯定有人好奇在HTTP规范中为什么要定义这个q值;还有在响应首部有一个名为Vary的首部,这个首部又有什么意义?如图所示:

二、内容协商总结

要讲清楚这两个问题,我们需要引入HTTP协议的内容协商概念:某一资源,服务器有多个版本,客户端告知服务器自己的偏好,服务器根据偏好选择合适的版本响应客户端的请求。

共有3种不同的方法可以决定服务器上哪个页面最适合客户端:让客户端来选择、服务器自动判定、让中间代理来选。这3种技术分别称为客户端驱动的协商、服务器驱动的协商以及透明协商。

(1)客户端驱动
    客户端发起请求,服务器发送可选项列表,客户端作出选择后在发送第二次请求。
    优点:比较容易实现;
    缺点:增加了时延,至少要发送两次请求,第一次请求获取资源列表,第二次获取选择的副本;

(2)服务器驱动
    服务器检查客户端的请求首部集并决定提供哪个版本的页面。
    优点:比客户端驱动的协商要快。HTTP提供了q机制,允许服务器近似匹配,还提供了vary首部供服务器告知下游的设备(如代理服务器)如何对请求估值;
    缺点:首部集不匹配,服务器要做猜测;

(3)透明协商
    某个中间设备(通常是缓存代理)代表客户端进行协商。
    优点:免除了web服务器的协商开销,比客户端驱动的协商要快;
    缺点:HTTP并没有提供相应的规范;

其中,服务器驱动的解决方案应用的较为广泛。

三、通用的内容协商首部集

客户端可以用下面列出的HTTP首部集发送用户的偏好信息:

Accept:告知服务器发送何种媒体类型;
Accept-Language:告知服务器发送何种语言;
Accept-Charset:告知服务器发送何种字符集;
Accept-Encoding:告知服务器采用何种编码;

    【注意】这些首部与实体首部非常类似。不过,这两种首部的用途截然不同。

    实体首部集像运输标签,它们描述了把报文从服务器传输给客户端的过程中必须的各种报文主体属性。

    而内容协商首部集是由客户端发送给服务器用于交换偏好信息的,以便服务器可以从文档的不同版本中选择出最符合客户端偏好的那个来提供服务。

服务器用下面列出的实体首部集来匹配客户端的Accept首部集:

Accept首部           实体首部
Accept          Content-Type
Accept-Language     Content-Language
Accept-Charset        Content-Type
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压缩,也就没法解压。

六、透明协商

透明协商机制试图从服务器上去除服务器驱动协商所需的负载,并用中间代理来代表客户端以使与客户端的报文交换最小化。假定代理了解客户端的预期,这样就可以代表客户端与服务器协商,在客户端请求内容的时候,代理已经收到了客户端的预期。

为了支持透明内容协商,服务器必须有能力告知代理,服务器需要检査哪些请求首部,以便对客户端的请求进行最佳匹配。HTTP/1.1规范中没有定义任何透明协商机制,但定义了Vary首部。服务器在响应中发送了Vary首部,以告知中间节点需要使用哪些请求首部进行内容协商。

代理缓存可以为通过单个URL访问的文档保存不同的副本。如果服务器把它们的决策过程传给缓存,这些代理就能代表服务器与客户端进行协商。缓存同时也是进行内容转码的好地方,因为部署在缓存里的通用转码器能对任意服务器,而不仅仅是一台服务器传来的内容进行转码。

1、缓存与备用候选

对内容进行缓存的时候是假设内容以后还可以重用。然而,为了确保对客户端请求回送的是正确的已缓存响应,缓存必须应用服务器在回送响应时所用到的大部分决策逻辑。

上面描述了客户端发送的Accept首部集,以及为了给每条请求选择最佳的响应,服务器使用的与这些首部集匹配的相应实体首部集。缓存也必须使用相同的首部集来决定回送哪个已缓存的响应。

下图展示了涉及缓存的正确及错误的操作序列。缓存把第一个请求转发给服务器,并存储其响应。对于第二个请求,缓存根据URL査找到了匹配的文档。但是,这份文档是法语版的,而请求者想要的是西班牙语版的。如果缓存只是把文档的法语版本发给请求者的话,它就犯了错误。

因此,缓存也应该把第二条请求转发给服务器,并保存该URL的响应与“备用候选”响应。缓存现在就保存了同一个URL的两份不同的文档,与服务器上一样。这些不同的版本称为变体(variant)或备用候选(alternate)。内容协商可看成是为客户端请求选择最合适变体的过程。

2、Vary首部

这里是浏览器和服务器发送的一些典型的请求及响应首部:

然而,如果服务器的决策不是依据Accept首部集,而是比如User-Agent首部的话,情况会如何?这不像听起来这么极端。例如,服务器可能知道老版本的浏览器不支持JavaScript语言,因此可能会回送不包含JavaScript的页面版本。如果服务器是根据其他首部来决定发送哪个页面的话,缓存必须知道这些首部是什么,这样才能在选择回送的页面时做出同样的逻辑判断。

HTTP的Vary响应首部中列出了所有客户端请求首部,服务器可用这些首部来选择文档或产生定制的内容(在常规的内容协商首部集之外的内容)。例如,若所提供的文档取决于User-Agent首部,Vary首部就必须包含User-Agent。

当新的请求到达时,缓存会根据内容协商首部集来寻找最佳匹配。但在把文档提供给客户端之前,它必须检査服务器有没有在已缓存响应中发送Vary首部。如果有Vary首部,那么新请求中那些首部的值必须与旧的已缓存请求里相应的首部相同。因为服务器可能会根据客户端请求的首部来改变响应,为了实现透明协商,缓存必须为每个已缓存变体保存客户端请求首部和相应的服务器响应首部,参见下图:

如果某服务器的Vary首部看起来像下面这样,大量不同的User-Agent和Cookie值将会产生非常多的变体:

Vary: User-Agent, Cookie

缓存必须为每个变体保存其相应的文档版本。当缓存执行査找时,首先会对内容协商首部集进行内容匹配,然后比较请求的变体与缓存的变体。如果无法匹配,缓存就从原始服务器获取文档。

参考链接:http://blog.csdn.net/meimeizhuzhuhua/article/details/70665344

     https://www.cnblogs.com/hellohuman/p/3989904.html

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

  1. HTTP协议的内容协商

    一.前言 我们在日常的抓包过程中经常可以看到以Accept开头的请求首部,比如:Accept-Language 有一个q值,肯定有人好奇在HTTP规范中为什么要定义这个q值:还有在响应首部有一个名为V ...

  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. 再看javascript执行上下文、变量对象

    突然看到一篇远在2010年的老文,作者以章节的形式向我们介绍了ECMA-262-3的部分内容,主要涉及到执行上下文.变量对象.作用域.this等语言细节.内容短小而精悍,文风直白而严谨,读完有酣畅淋漓 ...

  2. 01-Python的基础知识1

    基础即常识. - Python的对象模型 - Python中一切皆对象. - 内置对象:数字,字符串,列表,元组,集合等等. - 基本输入 - 基本模式    变量 = input("提示字 ...

  3. 深入set和dict

    一. 浅拷贝和深拷贝   浅拷贝:就是创建一个具有相同类型,相同值但不同id的新对象.  浅拷贝产生的新对象中可变对象的值在发生改变时,会对原对象的值也做出改变,因为这些值是同一个引用. a = [1 ...

  4. 聊聊jvm系列

    http://blog.csdn.net/column/details/talk-about-jvm.html

  5. python学习笔记07-元组 字典

    元组: 元组里面的元素不可修改  创建后只可读  不可写 一个元素的时候 在后面加一个逗号 字典: 无序的 Python 中唯一的映射类型 采用键值对的形式存储数据 key必须是可哈希的  可哈希表示 ...

  6. POJ 1154

    #include<iostream> #include<stdio.h> #define MAXN 20 using namespace std; int DFS(int i, ...

  7. Window History对象

    History 对象属性 length 返回浏览器历史列表中的 URL 数量. History 对象方法 back() 加载 history 列表中的前一个 URL. window.history.b ...

  8. Anaconda 入门详解

    Anaconda Anaconda简介 Anaconda是一个免费开源的Python和R语言的发行版本,用于计算科学(数据科学.机器学习.大数据处理和预测分析),Anaconda致力于简化包管理和部署 ...

  9. CS231n学习笔记-图像分类笔记(上篇)

    原文地址:智能单元 图像分类:所谓图像分类问题,就是已有固定的分类标签集合,然后对于输入的图像按照标签类别,将其打上标签. 下面先介绍一下一个简单的图像如何利用计算机进行分类: 例子:以下图为例,图像 ...

  10. 【数组】Next Permutation

    题目: Implement next permutation, which rearranges numbers into the lexicographically next greater per ...