1.引言

由于我主要是做Android开发的,所以Vary很陌生,今天看到OkHttp源码中,有对Vary的判断,就在网上查询并且仔细研究了一下,感觉比较有用,就记录一下。

2.讲解

简单说一下我对Vary一些理解,自己的一点总结。

Vary一般出现在HTTP请求的响应信息头部,比如像下面这样:

HTTP/1.0 200 OK
Date: Fri, 24 Sep 2010 23:09:32 GMT
Content-Type: application/json;charset=UTF-8
Content-Language: en-US
Vary: Accept-Encoding,User-Agent
Age: 1235
X-Cache: HIT from cache.kolich.local
X-Cache-Lookup: HIT from cache.kolich.local:80
Content-Length: 25090
Connection: close 

或者是这样

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 31 Dec 2013 16:34:48 GMT
Content-Type: application/x-javascript
Content-Length: 66748
Last-Modified: Tue, 31 Dec 2013 14:30:52 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "52c2d51c-104bc"
Expires: Fri, 29 Dec 2023 16:34:48 GMT
Cache-Control: max-age=315360000
Strict-Transport-Security: max-age=31536000
Accept-Ranges: bytes

Vary出现在响应信息中的作用是什么呢?首先这是由服务器端添加,添加到响应头部。大部分情况下是用在客户端缓存机制或者是缓存服务器在做缓存操作的时候,会使用到Vary头,会读取响应头中的Vary的内容,进行一些缓存的判断。接下来我们就来说一下Vary如何做缓存判断。

对于服务器提供的某个接口来说,有时候会出现不同种类的客户端对其进行网络请求获取数据,不同的客户端可能支持的压缩编码方式不同,可能有的客户端不支持压缩,那么服务器端返回的数据就不能压缩,有的支持gzip编码,那么服务器端就可以进行gzip编码返回给客户端,客户端获取到数据之后,做响应的gzip解码。还有种情况,对于不同的客户端,需要的内容不一样,比如针对特定,浏览器要求输出的内容不一样,比如在IE6浏览器上要输出不一样的内容,这就需要服务器端做不同的数据返回。所以说,服务器提供的同一个接口,客户端进行同样的网络请求,对于不同种类的客户端可能需要的数据不同,服务器端的返回方式返回数据也会不同。对于这个问题的解决,我想很多人是清除的,我们可以在请求信息添加Accept-Encoding、User-Agent等头部。

  1. Accept-Encoding表示客户端支持的编码格式,常见的编码格式有gzip/compress/deflate/identity,服务器端会根据客户端提供的Accept-Encoding对返回的内容进行编码,并通过添加响应头Content-Encoding表明服务器端使用的编码格式。详解请参考我的另一篇博客[连接];
  2. User-Agent表示客户端代理,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。这样服务器就能区别不同种类的客户端,做出不同的数据返回操作。

这些都没有问题,顺利的解决了我们上面提出的问题,然而,当使用到缓存的时候,就会有问题,比如要求针对IE5和IE6显示不同的数据,针对同一接口的同样的请求,缓存服务器中分别存储了IE5和IE6两份数据,由于同样的接口同样的请求,一旦服务器判定要从缓存中获取数据的话,很有可能会导致两个客户端的请求拿到同一份数据,这就会让那个数据展示出现问题;再比如说A类客户端支持压缩格式gzip,B类客户端不支持压缩,对于同一个接口同样的请求,如果服务器端打算从缓存服务器中取出数据返回的话,A、B两类客户端可能会收到同样的数据,这样要就会导致编解码出错。

这时候我们的Vary响应头就登场了,Vary的字面意思是“不一、多样化”,顾名思义,它的存在区分同样的网络请求的不同之处,其实就是通过头部信息来区分。一个简单的Vary头包括:

Vary: Accept-Encoding

Vary: Accept-Encoding,User-Agent

Vary: X-Some-Custom-Header,Host

Vary: *

Vary存在于响应头中,它的内容来自于请求头中相关字段,Vary头的内容如果是多条则用“,”分割。缓存服务器会将某接口的首次请求结果缓存下来(包括响应头中的Vary),后面在发生相同请求的时候缓存服务器会拿着缓存的Vary来进行判断。比如Vary: Accept-Encoding,User-Agent,那么Accept-Encoding与User-Agent两个请求头的内容,就会作为判断是否返回缓存数据的依据,当缓存服务器中相同请求的缓存数据的编码格式、代理服务与当前请求的编码格式、代理服务一致,那就返回缓存数据,否则就会从服务器重新获取新的数据。当缓存服务器中已经缓存了该条请求,那么某次服务器端的响应头中如果Vary的值改变,则Vary会更新到该请求的缓存中去,下次请求会对比新的Vary内容。

官方解释Vary头:告知下游的代理服务器,应当如何对以后的请求协议头进行匹配,以决定是否可使用已缓存的响应内容而不是重新从原服务器请求新的内容。

Vary: * ,这个我不太理解,我个人的理解是,当Vary的值为“*”时,意味着请求头中的那些字段的值不能用来区分当前请求是从缓存服务拿还是重新请求获取,在Android的OkHttp框架中,客户端接收到服务器的响应数据,进行缓存处理时,一旦判断响应头有Vary:*时,就不缓存该条数据。所以我猜想缓存服务器会不会也是这样,当Vary的值为“*”时,不做缓存。

3.总结

  1. Vary是作为响应头由服务器端返回数据时添加的头部信息;
  2. Vary头的内容来自于当前请求的Request头部Key,比如Accept-Encoding、User-Agent等;
  3. 缓存服务器进行某接口的网络请求结果数据缓存时,会将Vary一起缓存;
  4. HTTP请求,缓存中Vary的内容会作为当前缓存数据是否可以作为请求结果返回给客户端的判断依据;
  5. HTTP请求,响应数据中的Vary用来判断当前缓存中同请求的数据的Vary是否失效,如果缓存中的Vary与服务器刚拿到的Vary不一致,则可以进行更新。
  6. 当Vary的值为“*”,意味着请求头中的所有信息都不可作为是否从缓存服务器拿数据的判断依据。

4.疑问

当Vary的值为“*”时,意味着什么?Vary是否有更好的解释?官网的英文本人实在是能力有限翻译不过来,哪位大神有兴趣,可以指点一二,我不胜感激,我把官网的英文解释贴上来:

7.1.4. Vary

The "Vary" header field in a response describes what parts of a request message, aside from the method, Host header field, and request target, might influence the origin server's process for selecting and representing this response. The value consists of either a single asterisk ("*") or a list of header field names (case-insensitive).

Vary = "*" / 1#field-name

A Vary field value of "*" signals that anything about the request might play a role in selecting the response representation, possibly including elements outside the message syntax (e.g., the client's network address). A recipient will not be able to determine whether this response is appropriate for a later request without forwarding the request to the origin server. A proxy MUST NOT generate a Vary field with a "*" value.

A Vary field value consisting of a comma-separated list of names indicates that the named request header fields, known as the selecting header fields, might have a role in selecting the representation. The potential selecting header fields are not limited to those defined by this specification.

For example, a response that contains

Vary: accept-encoding, accept-language

indicates that the origin server might have used the request's Accept-Encoding and Accept-Language fields (or lack thereof) as determining factors while choosing the content for this response.

An origin server might send Vary with a list of fields for two purposes:

1. To inform cache recipients that they MUST NOT use this response to satisfy a later request unless the later request has the same values for the listed fields as the original request (Section 4.1 of [RFC7234]). In other words, Vary expands the cache key required to match a new request to the stored cache entry. Fielding & Reschke Standards Track [Page 70]

2. To inform user agent recipients that this response is subject to content negotiation (Section 5.3) and that a different representation might be sent in a subsequent request if additional parameters are provided in the listed header fields (proactive negotiation).

An origin server SHOULD send a Vary header field when its algorithm for selecting a representation varies based on aspects of the request message other than the method and request target, unless the variance cannot be crossed or the origin server has been deliberately configured to prevent cache transparency. For example, there is no need to send the Authorization field name in Vary because reuse across users is constrained by the field definition (Section 4.2 of [RFC7235]). Likewise, an origin server might use Cache-Control directives (Section 5.2 of [RFC7234]) to supplant Vary if it considers the variance less significant than the performance cost of Vary's impact on caching.

HTTP请求的响应头部Vary的理解相关推荐

  1. Wireshark 抓包分析 HTTP 请求、响应报文格式

    文章目录 报文结构 HTTP 请求报文的请求行 请求方法 GET/HEAD POST/PUT 其他方法 URI URI 的格式 URI 的编码 HTTP 响应报文的状态行 状态码 HTTP 请求.响应 ...

  2. NETGEAR拒绝连接请求_3分钟理解HTTP的请求与响应

    HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法. HTTPS(Hypertext Transfer ...

  3. HTTP请求头和响应头部包括的信息有哪些?(转)

    转载自:https://www.cnblogs.com/hxc555/p/6506154.html 每个HTTP请求和响应都会带有相应的头部信息.默认情况下,在发送XHR请求的同时,还会发送下列头部信 ...

  4. http请求报文头部vary信息

    原文出自http://mark.koli.ch/2010/09/understanding-the-http-vary-header-and-caching-proxies-squid-etc.htm ...

  5. 文加图, 理解Http请求与响应

    文加图, 理解Http请求与响应 1. http请求和响应步骤 在讲解OkHttp之前, 我们首先来个高清大图, 看下http请求的整个步骤, 有个整体概念. 2. http每一步详细内容 在一次完整 ...

  6. HTTP/HTTPS的请求和响应

    HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法. HTTPS(Hypertext Transfer ...

  7. Python爬虫(一)_HTTP的请求与响应

    HTTP和HTTPS HTTP(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收HTML页面的方法 HTTPS(HyperText Transfer Prot ...

  8. python爬虫(二)_HTTP的请求和响应

    HTTP和HTTPS HTTP(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收HTML页面的方法 HTTPS(HyperText Transfer Prot ...

  9. get请求报500_http请求和响应的全过程

    写在最前面的话: 最近心里总感觉怪怪的,也不知道为什么.直到今天我才发现我的公众号上有这么多用户呢.一个月因为种种原因没有更文章啦,心里总是过意不去,久等啦各位.以后尽我最大的努力更文章,哈哈哈!整理 ...

最新文章

  1. 基于SSM实现垃圾分类信息管理系统
  2. 浏览器ERR_PROXY_CONNECTION_FAILED解决方法
  3. 第三方提权之serv-u提权
  4. 承租方在使用过程中,若违反本公司的有关规定,公司有权在任何时候收回车辆...
  5. 第17课:RDD案例(join、cogroup等实战)
  6. 现在做Android开发有前途吗?社招面试心得
  7. LeetCode 1770. 执行乘法运算的最大分数(DP)
  8. Spring Cloud 5分钟搭建教程
  9. 看英语书记录的单词-5
  10. Leetcode︱448. Find All Numbers Disappeared in an Array找到所有数组中消失的数字.java
  11. 渴望成长的工程师-你了解一万小时定律吗
  12. shell的转义字符
  13. JAVA计算机毕业设计漫画网站系统(附源码、数据库)
  14. handler.post和handler.sendMessage的区别和联系
  15. n3160装微软服务器,英特尔赛扬N3160处理器性能跑分评测
  16. 帝国CMS数据字典 Ctrl+F查询
  17. 阿里云服务器ECS 搭建网站
  18. 706服务器型号,数据库版本706 此服务器支持661
  19. 面:常见面试题整理(操作系统)
  20. PKUWC2019垫底记

热门文章

  1. ibm service guide
  2. INSERT插入表记录
  3. gcc/g++ 命令的常用选项
  4. 《Android之大话设计模式》--设计原则 第三章:开放封闭原则 孙悟空任弼马温一职
  5. 【逼格瞬间提升100%】摆脱广告烦恼,拥有这5款插件,帮助你工作摸鱼两不误
  6. OpenFeign日志
  7. 跌破发行价——瑞幸咖啡这个案例,小白可能会疑惑的几个问题
  8. Venom 内网穿透
  9. C语言如何求n次方根
  10. 一篇文章搞懂设计模式