HTTP缓存看这一篇就够了( 二 )


协商缓存的请求和响应是需要相互配合的,可组合使用 。如下表:
版本/阶段
请求
响应
HTTP/1.0
If-Modified-Since/If-Unmodified-Since
Last-Modified
HTTP/1.1
If-None-Match/If-Match
ETag
协商缓存会先判断请求头中是否携带no-store 。如果携带,则直接返回最新的服务器文件 。

HTTP缓存看这一篇就够了

文章插图
2.2.1 HTTP/1.0 - Last-Modified客户端第一次向服务器请求资源时,服务器会返回资源 。同时会在响应头中添加Last-Modified?字段来表明资源的最后修改时间 。当客户端强制缓存失效后,会重新向服务器进行缓存有效性验证 。在验证的请求头中,会添加If-Modified-Since?字段 。服务器会对请求头中的If-Modified-Since?和其存储的资源Last-Modified?进行比较 。若If-Modified-Since?的时间不小于Last-Modified?,则资源有效,返回304(Not Modified)? 。否则返回资源本身,并且重新记录文件的Last-Modified 。
Last-Modified?:响应头携带的资源最后修改时间 。格式为last-modified:GMT 。
 
如:last-modified: Sat, 14 Jan 2023 08:40:00 GMT
  • 1.
 
If-Modified-Since?:请求头携带的资源是否在某个时间后有修改 。服务器会使用此值和其本身存储的时间进行比较 。格式为:If-Modified-Since:GMT? 。只可以用在 GET? 或 HEAD请求中 。
If-Unmodified-Since?:请求头携带的资源是否在某个时间后没有修改 。格式为:if-unmodified-since:GMT?  。有别于If-Modified-Since,If-Unmodified-Since?被用于POST?或其他非简单请求 。如果在If-Unmodified-Since?指定的时间内有过修改,则返回412(Precondition Failed) 。
HTTP缓存看这一篇就够了

文章插图
Last-Modified也是存在严重问题的 。
首先,Last-Modified只关注文件的最后修改时间,和文件内容无关 。所以文件内容在修改后又重新恢复,也会导致文件的最后修改时间改变 。此时客户端的请求则无法使用缓存 。
其次,Last-Modified?只能监听到秒级别的文件修改,如果文件在1秒内进行了多次修改,那么响应头返回的Last-Modified?的时间是不变的 。此时客户端因接收到响应304,会导致资源无法及时更新,使用缓存的资源文件 。
因此HTTP/1.1使用了ETag来进行缓存协商 。
2.2.1 HTTP/1.1 - ETag为了解决上述Last-Modified?可能存在的不准确的问题,HTTP/1.1推出了新的响应字段ETag?来进行协商缓存 。ETag?的优先级比Last-Modified高 。
服务器接收到浏览器请求后,会先进行If-None-Match与ETag?值的比较 。若相等,则资源有效,返回304(Not Modified)? 。否则返回资源本身,并且重新记录文件的ETag 。
ETag?:响应头携带的资源标识符 。格式为ETag:ETag-value可由服务器自行设置算法生成,通常是使用内容的散列或简单的使用版本号 。
 
如:etag: "I82YRPyDtSi45r0Ps/eo8GbnDfg="
  • 1.
 
If-None-Match?:请求头携带的是否无匹配文件字段 。优先级高于Last-Modified? 。当服务器没有任何资源的ETag?与请求头携带的ETag值完全一样时,返回最新的资源,否则服务器会返回304 。
 
如: if-none-match:"I82YRPyDtSi45r0Ps/eo8GbnDfg="
  • 1.
 
If-Match?:请求头携带的是否存在匹配文件字段 。对于简单请求需要搭配 Range?首部使用 。对于非简单请求,如PUT?,可用于上传ETag 。
 
如: if-match:"I82YRPyDtSi45r0Ps/eo8GbnDfg="
  • 1.
 
HTTP缓存看这一篇就够了

文章插图
三、总结通过前文,我们了解到 HTTP 缓存主要分:强制缓存、协商缓存 。强制缓存由Exipres(HTTP/1.0)、 Cache-Control(HTTP/1.1)控制 。客户端直接读本地缓存,不会再跟服务器端交互,状态码 200 。
协商缓存由 Last-Modified / If-Modified-Since(HTTP/1.0),Etag /If-None-Match(HTTP/1.1)进行有效性验证,每次请求需要让服务器判断一下资源是否更新过,从而决定客户端是否使用缓存,如果是,则返回 304,否则返回最新文件 。


推荐阅读