跳到主要内容

3. 前置条件头字段 (Precondition Header Fields)

本节定义用于对请求应用前置条件的 HTTP/1.1 头字段语法和语义. 第 5 节定义何时应用这些前置条件. 第 6 节定义存在多个前置条件时的求值顺序.

3.1. If-Match

If-Match 头字段使请求方法依赖于以下条件: 当 field-value 为 "*" 时, 接收方源服务器拥有目标资源的至少一个当前表示; 或者, 接收方源服务器拥有目标资源的当前表示, 且该表示的 entity-tag 与 field-value 中提供的 entity-tag 列表中的某个成员匹配.

源服务器在为 If-Match 比较 entity-tag 时 MUST 使用强比较函数 (第 2.3.2 节), 因为客户端希望该前置条件在表示数据发生任何变化时阻止方法被应用.

If-Match = "*" / 1#entity-tag

示例:

If-Match: "xyzzy"
If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-Match: *

If-Match 最常与会改变状态的方法 (例如 POST, PUT, DELETE) 一起使用, 以在多个用户代理可能并行操作同一资源时防止意外覆盖, 也就是防止 "lost update" 问题. 它也可与安全方法一起使用, 在选定表示与先前请求已存储 (或部分存储) 的表示不匹配时中止请求.

收到 If-Match 头字段的源服务器 MUST 在执行方法之前对条件求值 (第 5 节). 如果 field-value 为 "*", 且源服务器没有目标资源的当前表示, 则条件为 false. 如果 field-value 是 entity-tag 列表, 且列出的标签没有一个与选定表示的 entity-tag 匹配, 则条件为 false.

如果收到的 If-Match 条件求值为 false, 源服务器 MUST NOT 执行所请求的方法; 相反, 源服务器 MUST 以以下之一响应: a) 412 (Precondition Failed) 状态码; 或 b) 某个 2xx (Successful) 状态码, 前提是源服务器已验证请求的是状态变更, 且最终状态已经反映在目标资源的当前状态中.

缓存和中间节点可以忽略 If-Match 头字段, 因为它不适用于已存储响应.

3.2. If-None-Match

If-None-Match 头字段使请求方法依赖于以下条件: 当 field-value 为 "*" 时, 接收方缓存或源服务器没有目标资源的任何当前表示; 或者, 其选定表示的 entity-tag 与 field-value 中列出的任何 entity-tag 都不匹配.

接收方在为 If-None-Match 比较 entity-tag 时 MUST 使用弱比较函数 (第 2.3.2 节), 因为即使表示数据发生了变化, 弱 entity-tag 仍可用于缓存验证.

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 请求, 以最低的事务开销高效更新缓存信息. 当客户端希望更新一个或多个带有 entity-tag 的已存储响应时, 客户端在发出 GET 请求时 SHOULD 生成包含这些 entity-tag 列表的 If-None-Match 头字段; 这允许接收方服务器发送 304 (Not Modified) 响应, 表明其中某个已存储响应与选定表示匹配.

If-None-Match 也可以与 "*" 值一起使用, 以在客户端认为资源没有当前表示时, 防止不安全请求方法 (例如 PUT) 意外修改目标资源的现有表示.

收到 If-None-Match 头字段的源服务器 MUST 在执行方法之前对条件求值 (第 5 节). 如果 field-value 为 "*", 且源服务器拥有目标资源的当前表示, 则条件为 false. 如果 field-value 是 entity-tag 列表, 且列出的某个标签与选定表示的 entity-tag 匹配, 则条件为 false.

如果条件求值为 false, 源服务器 MUST NOT 执行所请求的方法; 相反, 如果请求方法是 GET 或 HEAD, 源服务器 MUST 以 a) 304 (Not Modified) 状态码响应, 对所有其他请求方法则以 b) 412 (Precondition Failed) 状态码响应.

3.3. If-Modified-Since

If-Modified-Since 头字段使 GET 或 HEAD 请求方法依赖于选定表示的修改日期是否晚于 field-value 中提供的日期. 如果该数据未发生变化, 就避免传输选定表示的数据.

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 的较老中间节点互操作.

如果收到的 field-value 不是有效的 HTTP-date, 或请求方法既不是 GET 也不是 HEAD, 接收方 MUST 忽略 If-Modified-Since 头字段.

If-Modified-Since 通常用于两个不同目的: 1. 允许高效更新没有 entity-tag 的缓存表示; 2. 将 Web 遍历范围限制为最近发生变化的资源.

收到 If-Modified-Since 头字段的源服务器 SHOULD 在执行方法之前对条件求值 (第 5 节). 如果选定表示的最后修改日期早于或等于 field-value 中提供的日期, 源服务器 SHOULD NOT 执行所请求的方法; 相反, 源服务器 SHOULD 生成 304 (Not Modified) 响应, 且只包含有助于识别或更新先前缓存响应的那些元数据.

3.4. If-Unmodified-Since

If-Unmodified-Since 头字段使请求方法依赖于选定表示的最后修改日期是否早于或等于 field-value 中提供的日期. 在用户代理没有该表示 entity-tag 的情况下, 该字段实现与 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 的较老中间节点互操作.

如果收到的 field-value 不是有效的 HTTP-date, 接收方 MUST 忽略 If-Unmodified-Since 头字段.

If-Unmodified-Since 最常与会改变状态的方法 (例如 POST, PUT, DELETE) 一起使用, 以在多个用户代理可能并行操作某个不随其表示提供 entity-tag 的资源时防止意外覆盖, 也就是防止 "lost update" 问题.

收到 If-Unmodified-Since 头字段的源服务器 MUST 在执行方法之前对条件求值 (第 5 节). 如果选定表示的最后修改日期晚于 field-value 中提供的日期, 源服务器 MUST NOT 执行所请求的方法; 相反, 源服务器 MUST 以以下之一响应: a) 412 (Precondition Failed) 状态码; 或 b) 某个 2xx (Successful) 状态码, 前提是源服务器已验证请求的是状态变更, 且最终状态已经反映在目标资源的当前状态中.

缓存和中间节点可以忽略 If-Unmodified-Since 头字段, 因为它不适用于已存储响应.

3.5. If-Range

If-Range 头字段提供一种特殊的条件请求机制, 类似于 If-MatchIf-Unmodified-Since 头字段, 但它指示接收方在验证器不匹配时忽略 Range 头字段, 从而传输新的选定表示, 而不是返回 412 (Precondition Failed) 响应. If-Range 在 [RFC7233] 第 3.2 节中定义.