跳至主要內容

浏览器缓存机制-请求头

Yihui计算机网络大约 4 分钟

浏览器缓存机制-请求头

相关头部字段

强缓存:

  • Expires
  • Cache-Control

协商缓存:

  • Etag、If-None-Match
  • Last-Modified、If-Modified-Since
  1. Cach-Control优先级高于Expires;
  2. Etag/If-Node-Match优先级高于Last-Modified/If-Modified-Since

强缓存

使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不再向服务器发起请求。强缓存策略可以通过两种方式来设置,分别是 HTTP 头信息中的 Expires 属性和 Cache-Control 属性。

Expires 是 HTTP 1.0 中的方式,因为它的一些缺点,在 HTTP 1.1 中提出了一个新的头部属性就是 Cache-Control 属性,Cache-Control 通用消息头字段,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。

当Expires和Cache-Control的 "max-age" 或者 "s-max-age" 指令同时存在时,会无视Expires,只遵循Cache-Control的指令内容。

Cache-Control

缓存请求指令

客户端可以在 HTTP 请求中使用的标准 Cache-Control 指令。

Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached

缓存响应指令

服务器可以在响应中使用的标准 Cache-Control 指令。

Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>

此外,还有扩展Cache-Control指令,拓展缓存指令不是核心 HTTP 缓存标准文档的一部分,使用前请注意检查兼容性。

常用指令内容

不包括实验性指令内容

可缓存控制

名称效果
public表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容(甚至是Post)。
private表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。
no-cache强制要求缓存把请求提交给原始服务器进行验证 (协商缓存验证)。
no-store不使用任何缓存

缓存时长控制

名称效果
max-age=<seconds>设置缓存存储的最大周期,超过这个时间缓存被认为过期 (单位秒)。与Expires相反,时间是相对于请求的时间。
s-maxage=<seconds>覆盖max-age或者Expires头,但是仅适用于共享缓存 (比如各个代理),私有缓存会忽略它。

更多见Cache-Control MDNopen in new window

Expires

Expires 响应头包含日期/时间, 即在此时候之后,响应过期。如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。

Expires: Wed, 21 Oct 2015 07:28:00 GMT

与Cache-Control对比可知:

响应报文中expires的时间值,是一个绝对值(时间点)

响应报文中Cache-Control为max-age=<seconds>,是相对值(时间差)

协商缓存

如果资源已过期,则表明强制缓存没有被命中,则开始协商缓存,向服务器发送带有 If-None-Match 或/和 If-Modified-Since 的请求,均为条件式请求首部。

If-Modified-Since是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。

If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。

服务器收到请求后,会优先根据 Etag 的值(If-None-Match的字段值与该资源在服务器的Etag值做对比)判断被请求的文件有没有做修改,Etag 值一致则认为没有修改,命中协商缓存,返回 304 状态码;如果不一致则有改动,直接返回新的资源文件带上新的 Etag 值并返回 200;

ETag 属性之间的比较采用的是弱比较算法,即两个文件除了每个字节都相同外,内容一致也可以认为是相同的。例如,如果两个页面仅仅在页脚的生成时间有所不同,就可以认为二者是相同的。

如果服务器收到的请求没有 Etag 值,则将 If-Modified-Since 和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回 304;不一致则返回新的 last-modified 和文件并返回 200;