• Cache-Control = 1#cache-directive
    • cache-directive = token [ “=” (token / quoted-string) ]
      • delta-seconds = 1*DIGIT
      • RFC规范中的要求是,至少能支持到2147483648(2^31)
  • 请求中的头部:max-age, max-stale, min-fresh, no-cache, no-store, no-transform, only-if-cached
  • 响应中的头部:max-age, s-maxage, must-revalidate, proxy-revalidate, no-cache, no-store, no-transform, public, private

Cache-Control头部的请求中的值

  • max-age:告诉服务器,客户端不会接收Age超出max-age秒的缓存
  • max-stale:告诉服务器,即使缓存不再新鲜,但陈旧秒数没有超过max-stale时,客户端仍打算使用。若max-stale后没有值,则表示无论过期多久客户端都可使用。
  • min-fresh:告诉服务器,Age至少经历min-fresh秒后缓存才可使用
  • no-cache:告诉服务器,不能直接使用已有缓存作为响应返回,除非带着缓存条件到上游服务器得到304验证码才可使用现有缓存
  • no-store:告诉代理服务器不要对该请求的响应缓存(实际有不少不遵循该规定的代理服务器)
  • no-transform:告诉代理服务器不要修改消息包体的内容
  • on-if-cache:告诉服务器仅能返回缓存的响应,否则若没有缓存则返回504错误码

Cache-Control头部在响应中的值

  • must-revalidate:告诉客户端一旦缓存过期,必须向服务器验证后才可使用
  • proxy-revalidate:与must-revalidate类似,但它仅对代理服务器的共享缓存有效
  • no-cache:告诉客户端不能直接使用缓存响应,使用前必须在源服务器验证得到304返回码。如果no-cache后值定头部,则客户端的后续请求及响应中不含有这些头则可直接使用缓存
  • max-age:告诉客户端缓存Age超出max-age秒后则缓存过期
  • s-maxage:与max-age相似,但仅针对共享缓存,且优先级高于max-age和Expires
  • public:表示无论私有缓存或者共享缓存,皆可将该响应缓存
  • private:表示该响应不能被代理服务器作为共享缓存。若private后值定头部,则在告诉代理服务器不能缓存值定的头部,但可缓存其他部分
  • no-store:告诉下游节点不能对响应进行缓存
  • no-transform:告诉代理服务器不能修改消息包体的内容

什么样的HTTP响应会缓存?RFC7234

  • 请求方法可以被缓存理解(不只GET方法)
  • 响应可以被缓存理解(404,206也可以被缓存)
  • 响应与请求的头部没有指明no-store
  • 响应中至少应含有一下头部中的1个或者多个:
    • Expires、max-age、s-maxage、public
    • 当响应中没有名确指示过期时间的头部时,如果响应码非常明确,也可以缓存
  • 如果缓存在代理服务器上
    • 不含有private
    • 不含有Authorization

使用缓存作为当前请求响应的条件

  • URI是匹配的
    • URI作为主要的缓存关键字,当一个URI同时对应多分缓存时,选择日期最近的缓存
    • 例如Nginx中的默认缓存关键字:proxy_cache_key
    • $scheme$proxy_host$request_uri
  • 缓存中的响应允许当前请求的方法使用缓存

使用缓存作为当前请求的响应条件

  • 缓存中的响应Vary头部指定的头部必须与请求中的头部相匹配
    • Vary = “*” / 1#field-name
    • Vary:* 意味着一定匹配失效
  • 当前请求以及缓存中的响应都不包含no-cache头部(Pargma: no-cache或者Cache-Control: no-cache)
  • 缓存中的响应必须时一下三者之一:
    • 新鲜的(时间上未过期)
    • 缓存中响应头名确告知可以使用过期的响应(如Cache-Control: max-stale=60)
    • 使用条件请求取服务器验证请求是否过期,得到304响应