3. Precondition Header Fields (前提条件头字段)
本节定义了用于对请求应用前提条件的 HTTP/1.1 头字段的语法和语义。第 5 节定义了何时应用前提条件。第 6 节定义了当存在多个前提条件时的评估顺序。
3.1. If-Match
If-Match 头字段使请求方法以接收方源服务器为条件, 当字段值为 "*" 时, 至少拥有目标资源的一个当前表示, 或者拥有目标资源的当前表示, 该表示具有与字段值中提供的实体标签列表中的成员匹配的实体标签。
源服务器在比较 If-Match 的实体标签时必须 (MUST) 使用强比较函数 (第 2.3.2 节), 因为客户端打算使用此前提条件来防止在表示数据发生任何更改时应用该方法。
If-Match = "*" / 1#entity-tag
示例:
If-Match: "xyzzy"
If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-Match: *
If-Match 最常用于状态改变方法 (例如 POST, PUT, DELETE), 以防止当多个用户代理可能并行作用于同一资源时发生意外覆盖 (即防止"丢失更新"问题)。它也可以与安全方法一起使用, 如果所选表示与先前请求已存储 (或部分存储) 的表示不匹配, 则中止请求。
接收到 If-Match 头字段的源服务器必须 (MUST) 在执行方法之前评估条件 (第 5 节)。如果字段值为 "*", 则当源服务器没有目标资源的当前表示时, 条件为 false。如果字段值是实体标签列表, 则当列出的标签都不与所选表示的实体标签匹配时, 条件为 false。
如果收到的 If-Match 条件评估为 false, 源服务器绝对不能 (MUST NOT) 执行请求的方法; 相反, 源服务器必须 (MUST) 以以下方式之一响应: a) 412 (Precondition Failed) 状态码, 或 b) 如果源服务器已验证正在请求状态更改且最终状态已反映在目标资源的当前状态中, 则使用 2xx (Successful) 状态码之一。
If-Match 头字段可以被缓存和中介忽略, 因为它不适用于存储的响应。
3.2. If-None-Match
If-None-Match 头字段使请求方法以接收方缓存或源服务器为条件, 当字段值为 "*" 时, 没有目标资源的任何当前表示, 或者具有所选表示, 其实体标签与字段值中列出的任何标签都不匹配。
接收方在比较 If-None-Match 的实体标签时必须 (MUST) 使用弱比较函数 (第 2.3.2 节), 因为即使表示数据发生了更改, 弱实体标签也可用于缓存验证。
If-None-Match = "*" / 1#entity-tag
示例:
If-None-Match: "xyzzy"
If-None-Match: W/"xyzzy"
If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
If-None-Match: *
If-None-Match 主要用于条件 GET 请求, 以最小的事务开销实现缓存信息的高效更新。当客户端希望更新一个或多个具有实体标签的存储响应时, 客户端应该 (SHOULD) 在发出 GET 请求时生成包含这些实体标签列表的 If-None-Match 头字段; 这允许接收方服务器发送 304 (Not Modified) 响应, 以指示这些存储响应之一何时与所选表示匹配。
If-None-Match 也可以使用值 "*" 来防止不安全的请求方法 (例如 PUT) 在客户端认为资源没有当前表示时无意中修改目标资源的现有表示。
接收到 If-None-Match 头字段的源服务器必须 (MUST) 在执行方法之前评估条件 (第 5 节)。如果字段值为 "*", 则当源服务器具有目标资源的当前表示时, 条件为 false。如果字段值是实体标签列表, 则当列出的标签之一与所选表示的实体标签匹配时, 条件为 false。
如果条件评估为 false, 源服务器绝对不能 (MUST NOT) 执行请求的方法; 相反, 源服务器必须 (MUST) 以以下方式之一响应: a) 如果请求方法是 GET 或 HEAD, 则使用 304 (Not Modified) 状态码, 或 b) 对于所有其他请求方法, 使用 412 (Precondition Failed) 状态码。
3.3. If-Modified-Since
If-Modified-Since 头字段使 GET 或 HEAD 请求方法以所选表示的修改日期比字段值中提供的日期更新为条件。如果该数据没有更改, 则避免传输所选表示的数据。
If-Modified-Since = HTTP-date
字段示例:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
如果请求包含 If-None-Match 头字段, 接收方必须 (MUST) 忽略 If-Modified-Since; If-None-Match 中的条件被认为是 If-Modified-Since 中条件的更准确替代, 两者仅为了与可能未实现 If-None-Match 的较旧中介进行互操作而组合使用。
如果收到的字段值不是有效的 HTTP-date, 或者如果请求方法既不是 GET 也不是 HEAD, 接收方必须 (MUST) 忽略 If-Modified-Since 头字段。
If-Modified-Since 通常用于两个不同的目的: 1) 允许对没有实体标签的缓存表示进行高效更新, 2) 将 Web 遍历的范围限制为最近更改的资源。
接收到 If-Modified-Since 头字段的源服务器应该 (SHOULD) 在执行方法之前评估条件 (第 5 节)。如果所选表示的最后修改日期早于或等于字段值中提供的日期, 源服务器不应该 (SHOULD NOT) 执行请求的方法; 相反, 源服务器应该 (SHOULD) 生成 304 (Not Modified) 响应, 仅包括对于识别或更新先前缓存的响应有用的那些元数据。
3.4. If-Unmodified-Since
If-Unmodified-Since 头字段使请求方法以所选表示的最后修改日期早于或等于字段值中提供的日期为条件。此字段实现了与 If-Match 相同的目的, 适用于用户代理没有表示的实体标签的情况。
If-Unmodified-Since = HTTP-date
字段示例:
If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
如果请求包含 If-Match 头字段, 接收方必须 (MUST) 忽略 If-Unmodified-Since; If-Match 中的条件被认为是 If-Unmodified-Since 中条件的更准确替代, 两者仅为了与可能未实现 If-Match 的较旧中介进行互操作而组合使用。
如果收到的字段值不是有效的 HTTP-date, 接收方必须 (MUST) 忽略 If-Unmodified-Since 头字段。
If-Unmodified-Since 最常用于状态改变方法 (例如 POST, PUT, DELETE), 以防止当多个用户代理可能并行作用于不提供实体标签的资源时发生意外覆盖 (即防止"丢失更新"问题)。
接收到 If-Unmodified-Since 头字段的源服务器必须 (MUST) 在执行方法之前评估条件 (第 5 节)。如果所选表示的最后修改日期比字段值中提供的日期更新, 源服务器绝对不能 (MUST NOT) 执行请求的方法; 相反, 源服务器必须 (MUST) 以以下方式之一响应: a) 412 (Precondition Failed) 状态码, 或 b) 如果源服务器已验证正在请求状态更改且最终状态已反映在目标资源的当前状态中, 则使用 2xx (Successful) 状态码之一。
If-Unmodified-Since 头字段可以被缓存和中介忽略, 因为它不适用于存储的响应。
3.5. If-Range
If-Range 头字段提供了一种特殊的条件请求机制, 类似于 If-Match 和 If-Unmodified-Since 头字段, 但指示接收方在验证器不匹配时忽略 Range 头字段, 从而导致传输新的所选表示而不是 412 (Precondition Failed) 响应。If-Range 在 [RFC7233] 的第 3.2 节中定义。