# 条件请求

过期的 response 不会被立即丢弃，可以询问 origin server 把 stale 变成 fresh 的，即 HTTP 的重新验证机制。重新验证是通过条件请求来完成的。

在用 `Cache-Control` 做缓存控制的时候，很多时候浏览器在使用前还必须去服务器验证是否是最新版。即先发一个 HEAD 请求，来获取资源的修改时间等元信息，然后再与缓存数据进行比较：如果没有改动就使用缓存，否则就再发一个 GET 请求，获取最新的版本。

然而，两个请求的网络成本太高了，所以 HTTP 协议就定义了一系列头字段，专门用来检查资源是否过期，从而把两个请求才能完成的工作合并在一个请求里做。而且，验证的责任也交给服务器，浏览器只需坐享其成。

![](https://605825044-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVUa7MztTVfoHQxXozBQf%2Fuploads%2FkljgBWtugKt6Cjz9feV3%2Fimage.png?alt=media\&token=eeccc524-2d72-4255-8127-0fd670ba0b45)

1. 第一次的响应报文，预先提供 `Last-modified` 和 `ETag`
2. 第二次请求时，就可以带上缓存里的原值，验证资源是否是最新的
3. 如果资源没有变，服务器就回应一个 `304 Not Modified`，表示缓存依然有效，浏览器就可以更新一下有效期，然后放心大胆地使用缓存了

<table><thead><tr><th width="205.33333333333331">Request</th><th width="150">Response</th><th>说明</th></tr></thead><tbody><tr><td></td><td><mark style="color:purple;">Last-modified</mark></td><td>文件的最后修改时间</td></tr><tr><td></td><td><mark style="color:purple;">ETag</mark></td><td>Entity Tag，实体标签，是资源的唯一标识<br>用来解决“修改时间无法准确区分文件变化”的问题<br>ETag 有强弱之分</td></tr><tr><td><mark style="color:purple;">If-Modified-Since</mark><br><mark style="color:purple;">If-None-Match</mark></td><td></td><td>验证资源否失效</td></tr><tr><td>If-Unmodified-Since</td><td></td><td></td></tr><tr><td>If-Match</td><td></td><td></td></tr><tr><td>If-Range</td><td></td><td></td></tr></tbody></table>
