HTTP 协议的缓存机制涉及到多个请求头字段,并且整个缓存机制的细节行为也存在各类状况的差别,譬如说何时访问本地缓存不发送请求,何时发送请求查看资源是否更新,获取 response 什么状况下更新缓存等。之前我对此只知其一;不知其二只是笼统的知道一些概念,譬如 Cache-Control 能够控制缓存的时间和是否须要缓存,可是缓存过时后的行为,有缓存后浏览器是否有 http 请求都不甚了解。因此特意 google 下,此篇是对此的知识梳理。php
什么状况下可使用本地缓存?譬如说咱们用 get 方式请求了一个资源 http://mytest.domain.com/static/images/bg.png
,那么咱们下次再请求这个图片资源的时候符合哪些条件可使用本地缓存呢?html
http://mytest.domain.com/static/images/bg.png
,若是是 http://mytest.domain.com/static/images/bg.png?t=12312321
就会发起新的请求,由于 url 不一样。注1:上述任何提一个条件均可以被 cache-control extension 覆盖算法
注2:response header中不只仅能够 Cache-Control: no-cache,还能够 Cache-Control: no-cache="Set-Cookie" 详见浏览器
浏览器是经过比较缓存剩余有效时间和当前缓存已存在时间来判断的:response_is_fresh = (freshness_lifetime > current_age)
。freshness_lifetime
取值优先级次序以下列表所示(排在上面的优先级越高):缓存
注1;若是有多个重复的上述头,那么是非法的,视做 response(资源)过时服务器
规范并无给出具体的算法,可是给出了最坏状况(but does impose worst-case constraints on their results),若是 response(资源)有 Last-Modified 头,那么推荐用从当前到lastmodified这个时间段的 10% 做为 freshness_lifetime
,而且 response(资源)的 current_age 若是已经超过24小时,必须在这个 response 上加上113 warn-code头。不多有浏览器实现了freshness_lifetime
的自助计算(推测),因此仍是仍是鼓励给出上述显式的1 - 3三种状况。网络
泛泛来讲就是 response(资源)在本地的驻足时间加上网络传输时间,由于网络传输时间的计算有多个条件,规范实在看的我头晕,因此具体计算规则详见规范dom
首先,若是第一次的 response(资源)头中显示申明了一些禁止缓存的头(譬如:"no-store" or "no-cache" 等等),就不存在过时不过时的问题,由于这个资源不容许缓存。其次,过时缓存也不必定不可用,若是在断网或者第二次请求带上 max-stale 这个请求头,那么浏览器可使用过时的缓存(masx-stale 表示在缓存过时后多少时间内浏览器依然可使用缓存)。碰到过时缓存,浏览器能够发送一个条件请求(conditional request)。这个请求的 url 依然是第一次请求的 url,只是会带上些当前资源的一些信息,以供服务器验证这个缓存是否依然可用仍是须要更新:google
服务器会根据不一样的条件请求头来验证资源,具体的行为详见规范,这里不细致展开。针对条件请求,服务器返回会有三种状况:url
若是是一个304的返回,规范说这个返回能够更新本地缓存,更新策略分三种:
假设第一次请求一个资源,返回 header 里面带上以下字段:
Cache-Control: max-age=600
Last-Modified: Wed, 28 Aug 2013 10:36:42 GMT
ETag: "124752e0d85461a16e76fbdef2e84fb9"
抛开细枝末节的东西,那么第二次请求一般大体流程图以下:
当前资源缓存是否过时:response_is_fresh = (freshness_lifetime > current_age) | ----------------------------------- | | 是 否 | | 发送请求,带上请求头 从本地缓存中获取资源(不发请求) If-Modified-Since: 此资源Last-Modified的值 If-None-Match: 此资源ETag的值 | 服务器根据 If-Modified-Since 和 If-None-Match 两个值判断资源是否更新过 | ------------------------- | | 是 否 | | 返回一个 status code:200 的 response 返回一个 status code:304 的 response response body 里面是请求的资源 response body 为空 | | 浏览器用 response body里面的资源 依然从本地缓存里面获取资源 替换本地缓存中的资源
当你去浏览器验证的时候可能会碰到一些特殊状况,就是缓存有效,可是你刷新浏览器依然发送的条件请求。实际上是由于浏览器在请求头中加入了一些料,譬如: Cache-Control: max-age=0。你刷新的方式能够有不少种,譬如:按F5,按ctrl+F5,在地址栏按回车等等。这些不一样的行为都会影响浏览器发送请求的行为。这里有一些参考《在浏览器地址栏按回车、F五、Ctrl+F5刷新网页的区别》