前言
该文章是基于自己的理解整理,旨在帮助自己更好的理解HTTP缓存,如有错误欢迎指正。
缓存分为强缓存、协商缓存,目的就是加快资源的获取时间(网页的加载速度),减少服务器的负担。
强缓存
不需要发送请求到服务端,直接读取浏览器的本地缓存。
强缓存的条件: Expires、Cache-Control 和 Pragma 3 个 Header 属性共同来控制。优先级是Pragma -> Cache-Control -> Expires
-
Expires
值为 no-cache时,客户端不会从本地读取缓存,会向服务器发送请求 -
Expires
Pragma是用来禁用缓存的, Expires是一个HTTP日期。用来告诉浏览器资源缓存过期时间,浏览器在发起请求时,会根据系统时间和Expires进行对比, 如果系统时间超过Expires时间,缓存就会失效。由于是和系统时间比较,所以当本地时间混乱时,会出现错误。 -
Cache-Control
Expires时间是相对服务器而言,无法保证和客户端时间统一”的问题。http1.1新增了 Cache-Control 来定义缓存过期时间。
作为请求首部时,cache-directive 的可选值有:
作为响应首部时,cache-directive 的可选值有:
协商缓存
当强缓存失效时或者请求头中设置了不走强缓存,就会协商缓存,即浏览器向服务器发出请求。
1, Last-Modified
服务器将资源传递给客户端时,会将资源的最后更改时间以“Last-Modified: GMT”的形式加在实体首部上一起返回给客户端。客服端为资源标记该信息。下次请求时,会把
该信息附带在请求报文中一并给服务器检查,若果传递时间和服务器上该资源最终修改时间是一致, 则返回 304 状态码。否则返回 200
1.1,If-Modified-Since: Last-Modified-value
例子:If-Modified-Since: Thu, 31 Mar 2016 07:07:52 GMT
作用:告诉服务器如果客户端传来的最终修改时间与服务器一致,则返回304和响应报头
1.2,If-Unmodified-Since: Last-Modified-value
值告诉服务器,若Last-Modified没有匹配上(资源在服务端的最后更新时间改变了),则应当返回412(Precondition Failed) 状态码给客户端。 Last-Modified 存在一定问题, 如果在服务器上,一个资源被修改了,但其实际内容根本没发生改变,会因为Last-Modified时间匹配不上而返回了整个实体给客户端(即使客户端缓存里有个一模一样的资源)。
2,Etag
解决Last-Modified可能存在的不准确的问题。 服务器会通过某种算法,给资源计算得出一个唯一标志符(比如md5标志),在把资源响应给客户端的时候,会在实体首部加上“ETag: 唯一标识符”一起返回给客户端。 客户端保留该字段。并在下一次请求时将其一并带过去给服务器。服务器只需要比较客户端传来的ETag跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
2.1 If-None-Match: ETag-value
If-None-Match: "5d8c72a5edda8d6a:3239" 告诉服务端如果 ETag 没匹配上需要重发资源数据,否则直接回送304 和响应报头即可。 当前各浏览器均是使用的该请求首部来向服务器传递保存的 ETag 值。
2.2 If-Match: ETag-value
告诉服务器如果没有匹配到ETag,或者收到了“*”值而当前并没有该资源实体,则应当返回412(Precondition Failed) 状态码给客户端。否则服务器直接忽略该字段。 需要注意的是,如果资源是走分布式服务器(比如CDN)存储的情况,需要这些服务器上计算ETag唯一值的算法保持一致,才不会导致明明同一个文件,在服务器A和服务器B上生成的ETag却不一样。