下面来讨论什么样的响应会被缓存,以及使用好已经缓存好的条件是什么。
缓存分为两步,首先将响应缓存下来,第二步将要发起一个请求的时候检查当前缓存是否可以使用缓存了的响应。
(1) 请求方法可以被缓存理解(不只于 GET 方法,Get方法是肯定可以被缓存的,非get方法也可以被缓存)
(2)响应码可以被缓存理解(404、206 也可以被缓存)
(3)响应与请求的头部没有指明 no-store
(4)响应中至少应含有以下头部中的 1 个或者多个:
- Expires、max-age、s-maxage、public
- 当响应中没有明确指示过期时间的头部时,如果响应码非常明确,也可以缓存
(5)如果缓存在代理服务器上
- 不含有 private(这里是说明不能使用共享缓存,而代理服务器上是可以使用共享缓存的)
- 不含有 Authorization
其他响应头部
• Pragma = 1#pragma-directive
• pragma-directive = "no-cache" / extension-pragma
• extension-pragma = token [ "=" ( token / quoted-string ) ]
• Pragma: no-cache与Cache-Control: no-cache 意义相同
使用缓存作为当前请求响应的条件
URI 是匹配的
- URI 作为主要的缓存关键字,当一个 URI 同时对应多份缓存时,选择日期最近的缓存
- 例如 Nginx 中默认的缓存关键字:proxy_cache_key $scheme$proxy_host$request_uri;
缓存中的响应允许当前请求的方法使用缓存
虽然有了缓存,但是想使用缓存还是有一些条件的,第一个url是需要匹配的,uri是需要作为缓存关键字的,uri会对应多份缓存,这个时候选择日期最近的缓存。
使用缓存作为当前请求响应的条件
- 缓存中的响应 Vary 头部指定的头部必须与请求中的头部相匹配:
Vary = “*” / 1#field-name
Vary: *意味着一定匹配失败(不是具体的某个头部)
• 当前请求以及缓存中的响应都不包含 no-cache 头部(Pragma: no-cache 或者 Cache-Control: no-cache)
• 缓存中的响应必须是以下三者之一:
• 新鲜的(时间上未过期)
• 缓存中的响应头部明确告知可以使用过期的响应(如 Cache-Control: max-stale=60)
• 使用条件请求去服务器端验证请求是否过期,得到 304 响应
Vary 缓存
客户端去访问,服务器端使用的是gzip编码,这个时候代理服务器上缓存的是gzip编码的内容,如果客户端2来访问的时候,那么它明确指出只能接受br算法来压缩的内容,这个时候虽然有同样的url,同样的url,这样是不可以返回的,第一次返回的响应当中有vary头部,vary头部说明必须根据content-encoding来进行,content-encoding写的是gizp,而client2里面的是br。这个时候必须向源服务器获取到响应。这个时候又存了一份br的响应。
当client3需要br的响应,那么就可以直接使用br的缓存返回client3。