持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
当缓存有一个已缓存的缓存项,并且想利用这个缓存项来作为客户端的响应时,缓存必须首先通过源服务器对其验证这个缓存项是否可用的过程称为验证。
验证模型
- 如果没有验证模型,那么每次验证只能重传一次完整响应与当前的缓存进行比较,http/1.1支持根据条件验证
- 当源服务器产生一个完整响应时,会附加一些验证项给这个响应,这些验证项会和响应一起保存。当客户端请求有缓存项的资源时,请求里也会包含一个相关的验证项
- 服务器核对请求里的验证项和当前实体本地的验证项是否匹配,如果匹配,会返回304的响应,并且不包含实体,如果不匹配,就返回完整响应,包含实体。如果验证项匹配,就减少返回完整响应的次数,如果不匹配,也减少了额外的一次请求过程
- 条件验证的请求和普通请求相似,除了条件请求会携带一些特殊的头部。一般有验证项头部的请求就是验证缓存是否可用的请求
- 协议中缓存验证条件存在的时候,请求会执行,如果没有验证条件,请求可能也会执行
最后修改日期(Last-Modified Dates)
- Last-Modified头部经常被用于缓存验证项,如果试题从Last-Modified值之后没有改变,那么缓存项被认为是有效的
试题标签缓存验证(Entity Tag Cache Validators)
- ETag头部是试题标签,提供了一个语义不是那么清楚的缓存验证项,当不方便保存修改日期的时候或者HTTP日期精确到1s不能被满足的时候,或源服务器希望避免日期产生冲突的时候,实体标签会更可靠
强弱验证项(Weak Strong Validators)
- 由于在验证的时候,会比较源服务器和缓存的验证项是否相同来确定这两个是否代表相同的试题,所以,当实体发生变化的时候,验证项也发生相应的变化,这样的验证项是强验证项
- 当服务器倾向于实体在发生重要的语义变化时才改变验证项,不发生重大改变就不改变验证项的是弱验证项
- 可以认为强验证是某个特定实体的验证,弱验证是实体语义等价的验证
- 实体标签通常是强验证的,但协议提供相关机制可以使实体标签标记为弱,从而变成弱验证
- 最后修改时间是用作验证的时候是弱验证的,除非一下情况可以认为是强验证
- 源服务器在与实体比较,并且源服务器知道实体不会在一秒内变化多次
- 客户端用If-Modified-Since头部来验证实体的缓存项,并且缓存项包含一个日期值,日期值是源服务器发送响应的时间,Last-Modified的值至少提前日期值60秒
- 中间缓存与缓存项比较,包含日期值,这个日期值是源服务器发送响应的时间并且Last-Modified的值至少提前日期值60秒
使用实体标签和最后修改时间的规则
- 源服务器:最好是同时发送实体标签和Last-Modified
- 客户端:如果源服务器提供了实体标签,客户端必须在任何缓存条件里请求实体标签,通过If-Match或If-None-Match利用实体标签的值。如果只有Last-Modified值时,客户端在非资范围缓存条件请求利用If-Modified-Since里利用Last-Modified的值
- 当源服务器收到一个请求中同时包含来自If-Modified-Since里的LastModified值和一个或多个试题标签的值时,源服务器不能返回304响应,除非请求里和所有值都保持一致
- 当源服务器收到一个请求中同时包含来自If-Modified-Since里的LastModified值和一个或多个试题标签的值时,已缓存请求和请求条件里的值一样,才会返回一个本地已缓存的响应给客户端
- http/1.1的客户端和服务器在请求和响应里尽可能的不传冗余的信息,在接收到信息后,系统会对接收到的验证值作最保守的假设
验证条件补充说明
-
实体标签的原则是只有服务发起的双方才知道的资源的语义,选择一个合适的缓存验证机制,所以在除了兼容http/1.0的Last-Modified值的比较,其余的比如字节数比较以及其他的头部值比较都不会用于验证一个缓存项