MDN 解释:
在 HTTP 协议中有一个“条件式请求”的概念,在这类请求中,请求的结果,甚至请求成功的状态,都会随着验证器与受影响资源的比较结果的变化而变化。这类请求可以用来验证缓存的有效性,省去不必要的控制手段,以及验证文件的完整性,例如在断点续传的场景下或者在上传或者修改服务器端的文件的时候避免更新丢失问题。
说人话:
条件请求就是附带条件的请求,客户端发送请求时,在请求首部字段具有 If-xxx
这种形式的请求都可以被称为条件请求,听名字就知道,服务器接收到条件请求后,需要判断这个条件是否满足来决定是否执行请求,而判断的方法是通过 验证器。
![](https://img.haomeiwen.com/i26873565/a45721b33a917f9a.png)
服务器会比对If-Match的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 的响应。
验证器
所有的条件请求首部都是试图去检测服务器上存储的资源是否与某一特定版本相匹配。为了达到这个目的,条件请求需要指明资源的版本。由于逐个字节去比较完整资源是不切实际的,况且这也并非总是想要的结果,所以在请求中会传递一个描述资源版本的值。这些值称为“验证器”,并且分为两大类:
-
Last-Modified :文件的最后修改时间
Last-Modified
是一个响应首部,其中包含源头服务器认定的资源做出修改的日期及时间。 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比ETag
要低,所以这是一个备用机制。包含有If-Modified-Since
或If-Unmodified-Since
首部的条件请求会使用这个字段。 -
ETag
ETag是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。首部字段 ETag 能告知客户端实体标识。另外,当资源更新时,ETag 值也需要更新。生成ETag 值时,并没有统一的算法规则,而仅仅是由服务器来分配,ETag 中有强 ETag 值和弱ETag 值之分。- 强 ETag 值:不论实体发生多么细微的变化都会改变其值。
- 弱 ETag 值:只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/。
条件首部
-
If-Modified-Since
If-Modified-Since 用于确认代理服务器或客户端的 缓存更新。在首次访问服务器时,服务器会将最新更新时间记录在 Last-Modified 与响应资源一并返回给客户端或者代理服务器,代理服务器会将资源进行本地缓存,然后返回给客户端。如果再次访问统一资源时,利用 If-Modified-Since 与服务器当前的 Last-Modified 比较来判断缓存是否失效,假如资源未发生变化,服务器就返回状态码为304 Not Modified
的响应;否则,资源发生了更新,响应状态为200 OK
,实现缓存资源的更新。 -
If-Unmodified-Since
首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相反。它的作用的是告知服务器,指定的请求资源只有在字段值内指定的日期时间之后,未发生更新 的情况下,才能处理请求。如果在指定日期时间后发生了更新,则以状态码412 Precondition Failed
作为响应返回。 -
If-Match
If-Match 前面已经举例介绍了,只有当 If-Match 的字段值跟 ETag 值匹配 一致 时,服务器才会接受请求。除此之外,可以使用星号(*)指定If-Match的字段值,针对这种情况,服务器将会忽略 ETag 的值,只要资源存在就处理请求。 -
If-None-Match
与 If-Match 首部字段的作用相反,只有在 If-None-Match 的字段值与 ETag 值 不一致 时,可处理该请求。在GET
或HEAD
请求方法中使用首部字段 If-None-Match 可 获取最新的资源。 -
If-Range
告诉服务器若指定的 If-Range 字段值(为 ETag 值或者时间)和请求资源的 ETag 值或时间相一致时,则作为 范围请求 处理。反之,则返回 全体资源。范围请求
Range
:指定范围发送的请求叫做范围请求
对一份10000字节大小的资源,如果使用范围请求,可以只请求5001~10000字节内的资源。
图源:《HTTP 图解》
针对范围请求,服务器响应会返回状态码为206 Partial Content
的响应报文。如果服务器端无法响应范围请求,则会返回状态码200 OK
和完整的实体内容。
如果不使用 If-Range 发送请求的。服务器端的资源如果发生更新,那客户端持有资源中的一部分也会随之无效,当然,范围请求作为前提是无效的。这时,服务器会暂且以状态码 412 Precondition Failed
作为响应返回,其目的是催促客户端再次发送请求。这样一来,与使用首部字段 If-Range 比起来,就需要花费两倍的功夫。
网友评论