http 200 from cache vs 304 not modified

在讨论这个问题之前先了解一下浏览器的缓存机制。浏览器的缓存机制有两种,一种是“Freshness(新鲜度,过期机制)”,另一种是“Validation(校验值,验证机制)”

“Freshness(新鲜度,过期机制)”:缓存副本有效期。若一个缓存副本是有效的、足够新的,则在这段有效期,浏览器直接从缓存中返回数据,无需再次发出实际请求。于是就有了“http 200 from cache”。

“Validation(校验值,验证机制)”:http设定了一套校验规则,用来校验当前客户端所缓存的资源是否仍然是新鲜的。当缓存失效时(Freshness优先级高于Validation),浏览器会在请求头中包含前置条件头,再次向服务器发送请求。当校验失效时,说明资源已经被修改或过期,浏览器需求重新获取资源内容。当校验未失效时,会返回“304 not modified”。

##与缓存有关的http消息报头##

1.Freshness(新鲜度,过期机制)有关的http消息报头有Cache-Control、Expires、Pragma等。

Cache-Control与Expires作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。

2.Validation(校验值,验证机制)有关的http消息报头有ETag、Last-Modified、If-Modified-Since、If-None-Match、If-Range、Cache-Control等。

Last-modified 和 If-Modefied-Since 一起工作。Last-modfied(在request头内) 指的是本地文件的修改时间。 If-Modefied-Since(在response头内)指的是服务器文件的修改时间。当Last-modefied与If-modefied-since一致时,说明文件没有被修改过,返回304,浏览器直接读取缓存中的文件。若不一致,则说明文件被修改过,返回200,浏览器重新从服务器换取文件。

If-None-Match 和 ETag 一起工作。 如果If-None-Match 和 ETag 一致,说明文件没有修改,返回304,使用缓存。否则重新从服务器获取文件。

既然已经有了 Last-Modified 已经能够知道本地缓存是否是最新的了,为什么还需要 Etag 呢?

主要是基于以下几个原因:

  1. Last-Modified 标注的最后修改时间只能精确到秒,如果有些资源在一秒之内被多次修改的话,他就不能准确标注文件的新鲜度了
  2. 如果某些资源会被定期生成,当内容没有变化,但 Last-Modified 却改变了,导致文件没使用缓存
  3. 有可能存在服务器没有准确获取资源修改时间,或者与代理服务器时间不一致的情形。

Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304

参考:
【Web缓存机制系列】2 – Web浏览器的缓存机制
http协议请求响应头中参数的疑问??
http://stackoverflow.com/questions/1665082/http-status-code-200-cache-vs-status-code-304