[14] [DFN[[CODE(HTTP)@en[[[If-Match:]]]]]] [[ヘッダー]]と
[DFN[[CODE(HTTP)@en[[[If-None-Match:]]]]]] [[ヘッダー]]は、
[[起源鯖]]の[[資源]]が指定した条件に[[一致]]する、またはしない場合のみ処理を実行するべきという[[条件付き要求]]であることとその条件を表します。

* 仕様書

[REFS[
- [3] '''[CITE@en[RFC 7232 - Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests]] ([TIME[2014-09-11 10:02:44 +09:00]] 版) <https://tools.ietf.org/html/rfc7232#section-3.1>'''
- [21] '''[CITE@en[RFC 7232 - Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests]] ([TIME[2014-09-11 10:02:44 +09:00]] 版) <https://tools.ietf.org/html/rfc7232#section-3.2>'''
- [19] [CITE@en[RFC 3229 - Delta encoding in HTTP]] ([TIME[2014-10-26 21:15:25 +09:00]] 版) <http://tools.ietf.org/html/rfc3229#section-7.1>
- [36] [CITE@en[RFC 3229 - Delta encoding in HTTP]] ([TIME[2014-10-26 21:15:25 +09:00]] 版) <http://tools.ietf.org/html/rfc3229#section-10.5.3>
- [41] [CITE@en[RFC 5789 - PATCH Method for HTTP]] ([TIME[2014-09-22 15:11:26 +09:00]] 版) <http://tools.ietf.org/html/rfc5789#section-2>
]REFS]

* 意味

[6] [CODE(HTTP)@en[[[If-Match:]]]] [[ヘッダー]]や
[CODE(HTTP)@en[[[If-None-Match:]]]] [[ヘッダー]]は、
[[要求メソッド]]を[[条件付き]]とするものです [SRC[>>3, >>21]]。
[[対象資源]]が指定された条件に一致する、またはしない時に[[要求]]で指定された処理を実行するべきことを表します。

* 構文

[9] [CODE(HTTP)@en[[[If-Match:]]]] や [CODE(HTTP)@en[[[If-None-Match:]]]]
の値は、 [CODE[[[*]]]] か、
または1つ以上の[[実体タグ]]の[[リスト]] ([CODE[#]]) です [SRC[>>3, >>21]]。

[FIG(railroad)[
= |
== [CODE[[[*]]]]
== =
=== [[実体タグ]]
=== *
==== [[OWS]]
==== [CODE[[[,]]]]
==== [[OWS]]
==== [[実体タグ]]
]FIG]

* 文脈

[15] [CODE(HTTP)@en[[[If-Match:]]]] は、
複数の[[利用者エージェント]]が同じ[[資源]]を並列に操作するかもしれない場合の上書き事故
(「[[lost update]]」問題) を防ぐために状態を変更する [CODE(HTTP)@en[[[POST]]]]、
[CODE(HTTP)@en[[[PUT]]]]、[CODE(HTTP)@en[[[DELETE]]]] のような[[メソッド]]と併用されることが多いです。
[SRC[>>3]]

[33] [CODE(HTTP)@en[[[If-None-Match:]] [[*]]]] は[[安全]]でない [CODE(HTTP)@en[[[PUT]]]]
のような[[要求メソッド]]を使って[[クライアント]]が現在の[[表現]]を持たないを操作しようとする時に、
意図せず既存の[[表現]]を編集してしまう一種の「[[lost update]]」問題
を避けるために使うことができます。 [SRC[>>21]]

[16] [CODE(HTTP)@en[[[If-Match:]]]] は[[安全メソッド]]で、
[[選択された表現]]の一部または全部が既に蓄積されている時に[[要求]]を中断するために使うこともできます
[SRC[>>3]]。

[32] [CODE(HTTP)@en[[[If-None-Match:]]]] は[[条件付きGET要求]]で、
最小のオーバーヘッドでキャッシュ情報を効率的に更新するために使います。
[[クライアント]]は、[[実体タグ]]つきで蓄積されている[[応答]]をいくつか更新したい時は、
[CODE(HTTP)@en[[[GET]]]] [[要求]]時にそれらの[[実体タグ]]を含む
[CODE(HTTP)@en[[[If-None-Match:]]]] を[[生成]]する[['''べきです''']]。 [SRC[>>21]]

[20] [[内容折衝]]などの理由で同じ [[URL]] に複数の[[表現]]が存在することもあり、
[[クライアント]]が複数の[[キャッシュ項目]]を保持していることがあるので、
[[実体タグ]]を複数指定することもできます。

[37] [CODE(HTTP)@en[[[A-IM:]]]] [[ヘッダー]]に[[差分符号化]]が含まれる場合は、 
[CODE(HTTP)@en[[[If-None-Match:]]]] [[ヘッダー]]に当該[[要求URL]] 
に対する以前の[[応答]]から得た1つ以上の[[実体タグ]]を含めなければなりません [SRC[>>36]]。

[34] [[差分符号化]]を使う場合には、[[クライアント]]が 
(そのものまたは復元するのに十分な[[差分]]を) 保持している[[実現値]]を明示し、
基準となる[[実現値]]を[[鯖]]に選ばせるために [CODE(HTTP)@en[[[If-None-Match:]]]]
[[ヘッダー]]に複数の[[実体タグ]]を指定することができます [SRC[>>19]]。

[40] [[HTTP認証]]の [[challenge]] を取得するために、
ダミーの[[実体タグ]]を [CODE(HTTP)@en[[[If-Match:]]]]
[[ヘッダー]]に指定する技法があります。

;; [[HTTP認証]>>17]参照。

[42] [CODE(HTTP)@en[[[PATCH]]]] [[要求]]を使って基準となる[[表現]]に対する差分を送信する場合は、
[CODE(HTTP)@en[[[If-Match:]]]] [[ヘッダー]]に[[実体タグ]]を指定する[['''べきです''']] [SRC[>>41]]。

* [CODE(HTTP)[*]]

[7] [CODE(HTTP)@en[[[If-Match:]] [[*]]]] が指定された時は、
[[対象資源]]が最低1つ現在の[[表現]]を有していれば、
条件を満たします [SRC[>>3]]。

[24] [CODE(HTTP)@en[[[If-None-Match:]] [[*]]]] が指定された時は、
[[対象資源]]が1つも現在の[[表現]]を有していないなら、
条件を満たします [SRC[>>21]]。

* 実体タグ

[8] [CODE(HTTP)@en[[[If-Match:]]]] に[[実体タグ]]が指定された時は、
そのいずれかが[[対象資源]]の現在の[[表現]]に一致すれば、
条件を満たします。ただし[[起源鯖]]は[[強い比較]]を使わなければ[['''なりません''']]。 [SRC[>>3]]

[25] [CODE(HTTP)@en[[[If-None-Match:]]]] に[[実体タグ]]が指定された時は、
そのいずれも[[選択された表現]]の[[実体タグ]]に一致しなければ、
条件を満たします。ただし[[受信者]]は[[弱い比較]]を使わなければ[['''なりません''']]。 [SRC[>>21]]

[18] [CODE(HTTP)@en[[[Meter]]]] の利用回数報告のために使う[[条件付き要求]]の場合、
[[実体タグ]]を複数指定することはできません。

;; [CODE(HTTP)@en[[[Meter]]]] 参照。

* 処理モデル

[17] [CODE(HTTP)@en[[[If-Match:]]]] や [CODE(HTTP)@en[[[If-None-Match:]]]]
の処理については、[[条件付き要求]]の項をご覧ください。

[35] [[差分符号化]]に関しては、[[差分符号化]]の項を参照してください。

[38] [[キャッシュ]]における[[差分符号化]]の処理については、[CODE(HTTP)[[[226]]]] を参照。

* 歴史

[FIG(quote)[
[FIGCAPTION[
[4] RFC 2068 (HTTP/1.1) 14.25; RFC 2616 (HTTP/1.1) 14.24 If-Match
]FIGCAPTION]

> The If-Match request-header field is used with a method to make it
conditional. A client that has one or more entities previously
obtained from the resource can verify that one of those entities is
current by including a list of their associated entity tags in the If-Match header field. [INS[Entity tags are defined in section 3.11.]]
The purpose of this feature is to allow efficient updates of cached
information with a minimum amount of transaction overhead.
It is also used, on updating requests, to prevent inadvertent modification of
the wrong version of a resource. As a special case, the value "*"
matches any current entity of the resource.

[CODE(HTTP)[If-Match]] 要求頭欄は、それを[[条件付]]とする[[方式]]と共に使います。
以前に[[資源]]から得た1個か複数個の[[実体]]を持っている[[クライアント]]は、
その実体群の1つが現行のものであることを、
[CODE(HTTP)[If-Match]] 頭欄にそれらの実体と関連付けられた[[実体札]]の並びを含めることで検証できます。[INS[実体札は3.11節で定義しています。]]
この機能の目的は、キャッシュした情報の効果的な更新最小限のやり取り overhead
で実現することです。この機能は、資源の誤った版を不注意に修正してしまうことを防ぐためにも使えます。
特別な場合として、値 [CODE(HTTP)[*]] は資源の現在の実体に一致します。

>
- If-Match = "If-Match" ":" ( "*" | 1#entity-tag )

> If any of the entity tags match the entity tag of the entity that
would have been returned in the response to a similar GET request
(without the If-Match header) on that resource, or if "*" is given
and any current entity exists for that resource, then the server MAY
perform the requested method as if the If-Match header field did not exist.

実体札のいずれかが同様の ([CODE(HTTP)[If-Match]] 頭なしの) [CODE(HTTP)[[[GET]]]] 
要求への応答で返されるであろう実体の実体札と一致するか、
または [CODE(HTTP)[*]] が与えられ、その資源に現在の実体が存在するなら、
[[サーバー]]は [CODE(HTTP)[If-Match]] 頭欄が存在しないかのように要求された方式を処理して'''構いません'''。

> A server MUST use the strong comparison function (see section [DEL[3.11]] [INS[13.3.3]])
to compare the entity tags in If-Match.

サーバーは、 [CODE(HTTP)[If-Match]] 中の実体札を比較するのに[[強い比較]]関数を使わなければ'''なりません'''。

> If none of the entity tags match, or if "*" is given and no current
entity exists, the server MUST NOT perform the requested method, and
MUST return a 412 (Precondition Failed) response. This behavior is
most useful when the client wants to prevent an updating method, such
as PUT, from modifying a resource that has changed since the client
last retrieved it.

実体札のどれもが一致しなかったか、または [CODE(HTTP)[*]]
が与えられたものの現在実体が存在しない場合は、サーバーは要求された方式を実行しては'''ならず'''、
[CODE(HTTP)[[[412]]]] (前条件失敗) 応答を返さなければ'''なりません'''。
この振る舞いは、 [CODE(HTTP)[[[PUT]]]] のような更新する方式で、
クライアントが最後にそれを取り出してから変更されている資源を修正してしまうことを防ぎたい時に有用です。

> If the request would, without the If-Match header field, result in
anything other than a 2xx [INS[or 412]] status, then the If-Match header
MUST be ignored.

[CODE(HTTP)[If-Match]] 頭欄がなければ要求の結果が [CODE(HTTP)[[[2xx]]]] 状態または
[CODE(HTTP)[[[412]]]] 状態以外のものになるとしたら、
[CODE(HTTP)[If-Match]] 頭は無視しなければ'''なりません'''。

> The meaning of "If-Match: *" is that the method SHOULD be performed
if the representation selected by the origin server (or by a cache,
possibly using the Vary mechanism, see section [DEL[14.43]] [INS[14.44]]) exists, and
MUST NOT be performed if the representation does not exist.

[CODE(HTTP)[If-Match: *]] の意味は、その方式は[[起源サーバー]]によって
(または[[キャッシュ]]によって、もしかすると [CODE(HTTP)[[[Vary]]]] 機構を使って)
選択された表現が存在するときに実行される'''べき'''であり、
表現が存在しないときには実行しては'''ならない'''ということです。

> A request intended to update a resource (e.g., a PUT) MAY include an
If-Match header field to signal that the request method MUST NOT be
applied if the entity corresponding to the If-Match value (a single
entity tag) is no longer a representation of that resource. This
allows the user to indicate that they do not wish the request to be
successful if the resource has been changed without their knowledge.

資源を更新する意図の要求 (例えば [CODE(HTTP)[PUT]])
は、 [CODE(HTTP)[If-Match]] 値 (1つの実体札) の対応する実体がもはやその資源の表現ではないときにその要求方式を適用しては'''ならない'''ことを通知するために
[CODE(HTTP)[If-Match]] 頭欄を含めても'''構いません'''。
これにより、利用者が、彼らの知識なしに資源が変更されているとしたら要求が成功することを望まないことを示すことができます。

> Examples:
- If-Match: "xyzzy"
- If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
- If-Match: *

[INS[

> The result of a request having both an If-Match header field and
either an If-None-Match or an If-Modified-Since header fields is
undefined by this specification.

[CODE(HTTP)[If-Match]] 頭欄と [CODE(HTTP)[[[If-None-Match]]]]
頭欄または [CODE(HTTP)[[[If-Modified-Since]]]] 頭欄のいずれかを持っている要求の結果は子の仕様書では未定義とします。
]INS]
]FIG]

[FIG(quote)[
[FIGCAPTION[
[22] RFC 2068・2616 (HTTP/1.1) 14.26 If-None-Match
]FIGCAPTION]

> The If-None-Match request-header field is used with a method to make
it conditional. A client that has one or more entities previously
obtained from the resource can verify that none of those entities is
current by including a list of their associated entity tags in the
If-None-Match header field. The purpose of this feature is to allow
efficient updates of cached information with a minimum amount of
transaction overhead. It is also used[DEL[, on updating requests,]] to prevent [INS[a method (e.g. PUT)]] [DEL[inadvertent modification of a resource which was not known to]] [INS[from inadvertently modifying an existing resource when the client believes that the resource does not]] exist.

[CODE(HTTP)[If-None-Match]] 要求頭欄は、それを条件付とする[[方式]]とともに使います。
以前に資源から得た1個か複数個の実体を持っているクライアントは、その実体群のどれもが現行のものではないことを、 [CODE(HTTP)[If-None-Match]] 頭欄にそれらの実体と関連付けられた実体札の並びを含めることで検証できます。
この機能の目的は、キャッシュした情報の効果的な更新を最小限のやり取り overhead で実現することです。この機能は、[DEL[更新する要求で、]]クライアントがその資源は存在しないと信じている時に既存の資源を不注意に修正してしまうことを防ぐためにも使えます。

> As a special case, the value "*" matches any current entity of the resource.

特別な場合として、値 [CODE(HTTP)[*]] は資源の現在の実体に一致します。

>
-If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )

> If any of the entity tags match the entity tag of the entity that
would have been returned in the response to a similar GET request
(without the If-None-Match header) on that resource, or if "*" is
given and any current entity exists for that resource, then the
server MUST NOT perform the requested method[INS[, unless required to do so because the resource's modification date fails to match that supplied in an If-Modified-Since header field in the request]].
Instead, if the request method was GET or HEAD, the server SHOULD
respond with a 304 (Not Modified) response, including the cache-related [DEL[entity-]]header fields
(particularly ETag) of one of the entities that matched. For all
other request methods, the server MUST respond with a status of
412 (Precondition Failed).

実体札のいずれかが同様の ([CODE(HTTP)[If-None-Match]] 頭なしの) 
[CODE(HTTP)[[[GET]]]] 要求への応答で返されるであろう実体の実体札と一致するか、
または [CODE(HTTP)[*]] が与えられ、その資源に現在の実体が存在するなら、[INS[資源の修正日付が要求の [CODE(HTTP)[[[If-Modified-Since]]]] 頭欄で供給されたものと一致しなかったためにそうする必要がある場合を除き、]]
サーバーは要求された方式を処理しては'''なりません'''。
代わりに、要求方式が [CODE(HTTP)[[[GET]]]] または [CODE(HTTP)[[[HEAD]]]]
であるなら、サーバーは、その一致する実体の一つのキャッシュ関連の頭欄 (特に [CODE(HTTP)[[[ETag]]]])
を含めた [CODE(HTTP)[[[304]]]] (未修正) 応答で応答する'''べきです'''。
他のすべての要求方式では、サーバーは [CODE(HTTP)[[[412]]]] (前条件失敗)
の状態で応答しなければ'''なりません'''。

> See section 13.3.3 for rules on how to determine if two [DEL[entity]] [INS[entities]] tags
match. The weak comparison function can only be used with GET or HEAD requests.

二つの実体札の一致をどう決定するかの規則は13.3.3節を参照。
[[弱い比較]]関数は [CODE(HTTP)[GET]] または [CODE(HTTP)[HEAD]] の要求でのみ使うことができます。

> If none of the entity tags match, [DEL[or if "*" is given and no current entity exists,]]
then the server MAY perform the requested method as if
the If-None-Match header field did not exist[INS[, but MUST also ignore any If-Modified-Since header field(s) in the request. That is, if no entity tags match, then the server MUST NOT return a 304 (Not Modified) response]].

実体札のいずれもが一致しなかった[DEL[か、[CODE(HTTP)[*]] が与えられ現在の実体が存在しない]]なら、
サーバーは要求された方式を [CODE(HTTP)[If-None-Match]] 頭欄(群)が要求に存在しなかったものとしてその要求された方式を実行して'''構いません'''[INS[が、要求にある [CODE(HTTP)[[[If-Modified-Since]]]] 頭欄(群)も無視しなければ'''なりません'''。つまり、実体札がどれも一致しなければ、サーバーは [CODE(HTTP)[[[304]]]] (未修正) 応答を返さなければ'''なりません''']]。

> If the request would, without the If-None-Match header field, result
in anything other than a 2xx [INS[or 304]] status, then the If-None-Match
header MUST be ignored. [INS[(See section 13.3.4 for a discussion of server behavior when both If-Modified-Since and If-None-Match appear in the same request.)]]

[CODE(HTTP)[If-None-Match]] 頭欄がなければ要求の結果が [CODE(HTTP)[[[2xx]]]] 状態[INS[または [CODE(HTTP)[[[304]]]] 状態]]以外のものになるとしたら、 
[CODE(HTTP)[If-None-Match]] 頭は無視しなければなりません。[INS[([CODE(HTTP)[If-Modified-Since]] と [CODE(HTTP)[If-None-Match]] の両方が同じ要求に現れる時のサーバーの振る舞いについての議論は13.3.4節を参照。)]]

> The meaning of "If-None-Match: *" is that the method MUST NOT be
performed if the representation selected by the origin server (or by
a cache, possibly using the Vary mechanism, see section [DEL[14.43]] [INS[14.44]])
exists, and SHOULD be performed if the representation does not exist.
This feature [DEL[may]] [INS[is intended to]] be useful in preventing races between PUT operations.

[CODE(HTTP)[If-None-Match: *]] の意味は、その方式は起源サーバーによって (またはキャッシュによって、もしかすると [CODE(HTTP)[[[Vary]]]] 機構を使って) 選択された表現が存在しないときに実行しては'''ならず'''、表現が存在しないときには実行する'''べき'''だということです。
この機能は [CODE(HTTP)[[[PUT]]]] 操作間の競合を防ぐのに有用であることを意図しています。

> Examples:

>
-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: *

[INS[
> The result of a request having both an If-None-Match header field and
either an If-Match or an If-Unmodified-Since header fields is
undefined by this specification.

[CODE(HTTP)[If-None-Match]] 頭欄と [CODE(HTTP)[[[If-Match]]]] 頭欄または [CODE(HTTP)[[[If-Unmodified-Since]]]] 頭欄のいずれかを持っている要求の結果はこの仕様書では未定義とします。
]INS]
]FIG]

[FIG(quote)[
[FIGCAPTION[
[5] RFC 2326 12.22 If-Match
]FIGCAPTION]

> See [H14.25].

> This field is especially useful for ensuring the integrity of the
presentation description, in both the case where it is fetched via
means external to RTSP (such as HTTP), or in the case where the
server implementation is guaranteeing the integrity of the
description between the time of the DESCRIBE message and the SETUP
message.

[1] この欄は、表現記述の完全性を確認するのに、これが RTSP
以外の手段 (例えば HTTP) 
で入手した場合においても或いはサーバー実装が
DESCRIBE メッセージの時刻及び SETUP
メッセージ間の記述の正当性を保証する場合においても、特に有用です。

> The identifier is an opaque identifier, and thus is not specific to
any particular session description language.

[2] 識別子は[RUBYB[不透明] [opaque]]識別子で、従ってどの特定の
session 記述言語にも依存しません。
]FIG]

[REFS[
- [413] [CITE@en[RFC 7252 - The Constrained Application Protocol (CoAP)]]
( ([TIME[2014-06-27 00:59:37 +09:00]] 版))
<http://tools.ietf.org/html/rfc7252#section-5.10.8.1>
- [23] [CITE@en[RFC 7252 - The Constrained Application Protocol (CoAP)]]
( ([TIME[2014-06-27 00:59:37 +09:00]] 版))
<http://tools.ietf.org/html/rfc7252#section-5.10.8.2>
]REFS]

* 例

[FIG(list)[
[FIGCAPTION[
[10] [CODE(HTTP)@en[[[If-Match:]]]] の例 [SRC[>>3]]
]FIGCAPTION]

- [11] [CODE(HTTP)[If-Match: "xyzzy"]]
- [12] [CODE(HTTP)[If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"]]
- [13] [CODE(HTTP)[If-Match: *]]
]FIG]

[FIG(list)[
[FIGCAPTION[
[26] [CODE(HTTP)@en[[[If-None-Match:]]]] の例 [SRC[>>21]]
]FIGCAPTION]

- [27] [CODE(HTTP)[If-None-Match: "xyzzy"]]
- [28] [CODE(HTTP)[If-None-Match: W/"xyzzy"]]
- [29] [CODE(HTTP)[If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"]]
- [30] [CODE(HTTP)[If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"]]
- [31] [CODE(HTTP)[If-None-Match: *]]
]FIG]

* 関連

[39] [CODE(HTTP)@en[[[Overwrite:]]]] は [CODE(HTTP)@en[[[If-Match:]] [[*]]]]
と似ていますが、[[対象資源]]ではなく終点資源に適応される点が異なります。

[FIG(quote)[
[FIGCAPTION[
[43] [CITE[Orchestrate]]
([[Orchestrate]] 著, [TIME[2016-03-08 10:22:00 +09:00]] 版)
<https://orchestrate.io/docs/apiref>
]FIGCAPTION]

> Conditional headers can be used to specify a pre-condition that determines whether the patch operation happens. The If-Match header specifies that the patch operation will succeed if and only if the ref value matches current stored ref. A failed If-Match patch-merge request will return a 412 Error "item_version_mismatch".

]FIG]


[44] [CITE@en[RFC 4791 - Calendaring Extensions to WebDAV (CalDAV)]]
([TIME[2017-09-24 16:22:36 +09:00]])
<https://tools.ietf.org/html/rfc4791#section-5.3.2>

[FIG(quote)[
[FIGCAPTION[
[45] [CITE@en[Buckets — Kinto 8.1.5 documentation]]
([TIME[2018-02-21 01:03:17 +09:00]])
<https://kinto.readthedocs.io/en/latest/api/1.x/buckets.html>
]FIGCAPTION]

> If the If-Match: "<timestamp>" request header is provided as described in the section about timestamps, and if the list has changed meanwhile, a 412 Precondition Failed error is returned.

]FIG]


[FIG(quote)[
[FIGCAPTION[
[46] [CITE@en[Buckets — Kinto 8.1.5 documentation]]
([TIME[2018-02-21 01:03:17 +09:00]])
<https://kinto.readthedocs.io/en/latest/api/1.x/buckets.html>
]FIGCAPTION]

> For cache and concurrency control, an ETag response header gives the value that consumers can provide in subsequent requests using If-Match and If-None-Match headers (see section about timestamps).

]FIG]


[47] [CITE@en[Server timestamps — Kinto 8.1.5 documentation]]
([TIME[2018-02-21 01:03:20 +09:00]])
<https://kinto.readthedocs.io/en/latest/api/1.x/timestamps.html>