HTTP协议:页面缓存之Cache-Control 和 Etag

Cache-Control是HTTP协议的一部分,是在请求和响应中必须服从的指令,通常用于提高页面加载,阻止页面缓存对请求和响应造成不利的干扰。
Cache-Control 为单向指令,即请求中存在的指令,并不意味着响应中存在同样的指令

一、请求

1. Cache-Control

RFC:7234#5.2.1 Request Cache-Control Directives

允许的指令 含义
max-age delta-seconds 客户端不愿意接受age超过这个值的缓存。并且不接受过期缓存,除非max-stale存在。
max-stale delta-seconds 如果有值,客户端可以接受过期时间不超过指定值的缓存 如果没有值,客户端愿意接受过期缓存而无论过期过久。
min-fresh delta-seconds 客户端愿意接受一个新鲜度不小于当前age加上指定时间的响应。简单说在指定的后续一段时间内不会过期的响应。
no-cache 客户端示意缓存,在使用缓存的时候必须进行校验。
no-store 客户端示意缓存,不要存储本次请求的响应。但是对于已经缓存的内容则没有影响。
no-transform 不得对资源进行转换或转变。Content-Encoding, Content-Range, Content-Type等HTTP头不能由代理修改。例如,非透明代理可以对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。 no-transform指令不允许这样做。
only-if-cached 客户端只接受缓存给出的响应,如果缓存没有命中应该返回一个504

2. ETag

Etag 是URL的Entity Tag,用于标示URL对象是否改变,区分不同语言和Session等等。具体内部含义是使服务器控制的,就像Cookie那样。
通常把ETags和GET请求的“If-None-Match”头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生ETag,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。

请求流程

Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match.请求一个文件的流程可能如下:
====第一次请求===
1.客户端发起 HTTP GET 请求一个文件;
2.服务器处理请求,返回文件内容和一堆Header,当然包括Etag(例如”2e681a-6-5d044840”)(假设服务器支持Etag生成和已经开启了Etag).状态码200
====第二次请求===
1.客户端发起 HTTP GET 请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头的内容就是第一次请求时服务器返回的Etag:2e681a-6-5d044840
2.服务器判断发送过来的Etag和计算出来的Etag匹配,因此If-None-Match为False,不返回200,返回304,客户端继续使用本地缓存;

作用

Etag 主要为了解决 Last-Modified 无法解决的一些问题。
1. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
2. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)
3. 某些服务器不能精确的得到文件的最后修改时间;
为此,HTTP/1.1引入了 Etag(Entity Tags).Etag仅仅是一个和文件相关的标记,可以是一个版本标记,比如说v1.0.0或者说”2e681a-6-5d044840”这么一串看起来很神秘的编码。但是HTTP/1.1标准并没有规定Etag的内容是什么或者说要怎么实现,唯一规定的是Etag需要放在”“内。
4. 有些URL是多语言的网页,相同的URL会返回不同的内容。还有不同的Session有不同的Cookie也就有不同的内容。这种情况下如果过 Proxy,Proxy就无法区分导致串门,只能简单的取消cache功能。Etag解决了这个问题,因为它能区分相同URL不同的对象。

二、响应

1. Cache-Control

RFC:7234#5.2.2 Response Cache-Control Directives

允许的指令 含义
must-revalidate 一旦缓存过期,必须向源服务器进行校验,不得使用过期内容。如果无法连接必须返回504。
proxy-revalidate 与must-revalidate相同,但仅对公共缓存生效。
no-cache field-name 如果值,在没有成功通过源站校验的情况下不得使用缓存。 有值,在进行验证的时候不要发送值指示的头域。 如Cache-Control: no-cache="set-cookie,set-cookie2",表示不要携带cookie进行验证。
no-store 不要缓存当前请求的响应
no-transform 与请求头语义相同
public 任何缓存都可以进行缓存,即使响应默认是不可缓存或仅私有缓存可存的情况。
private field-name 没有值,公有缓存不可存储;即使默认是不可缓存的,私有缓存也可以存储 。有值,将无值时的作用,限制到指定头字段上。公有有缓存不可存储指定的头字段,而其他字段可以缓存。
max-age delta-seconds 在经过指定时间后将过期
s-maxage delta-seconds 指定响应在公共缓存中的最大存活时间,它覆盖max-age和expires字段。

三、参考资料

Cache-Control头各个值的说明
RFC 7234
ETag:MDN 百度百科

猜你喜欢

转载自blog.csdn.net/qq_29753285/article/details/81453488