/
181.txt
153 lines (127 loc) · 10.8 KB
/
181.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
[8] 事前条件の指定がある[[要求]]のことを、[DFN[[RUBYB[条件付き要求]@en[conditional request]]]]といいます。
[[鯖]]は事前条件が満たされる場合には[[要求メソッド]]で指定された処理を[[対象資源]]に対して実行しますが、
事前条件が満たされなければ処理は実行せずにエラーを返します。
[9] [[条件付き要求]]は、[[キャッシュ]]より新しい場合のみ[[資源]]を取得したい時や、
他者の編集との衝突に注意しつつ[[鯖]]にある[[資源]]を更新したい時などに使われます。
* 仕様書
[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>'''
-- [10] [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>
-- [12] [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>
-- [14] [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.3>
-- [25] [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.4>
-- [18] [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-5>
-- [29] [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-6>
- [1] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-06-07 01:55:45 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-5.2>
- [28] [CITE@en[RFC 7233 - Hypertext Transfer Protocol (HTTP/1.1): Range Requests]] ([TIME[2014-09-11 09:57:55 +09:00]] 版) <https://tools.ietf.org/html/rfc7233#section-3.2>
]REFS]
* 意味
[4] [DFN[[RUBYB[[[条件付き要求]]]@en[conditional request]]]]は、
[[対象資源]]に[[要求メソッド]]の[[意味]]を適用する前に確認されるべき事前条件を示す[[ヘッダー]]をいくつか含む[[要求]]です
[SRC[>>3 1.]]。
[FIG(list)[
- [5] 条件付き [CODE(HTTP)@en[[[GET]]]] [[要求]]は、
[[HTTPキャッシュ]]の更新のための最も効率的な仕組みです [SRC[>>3 1.]]。
- [6] [CODE(HTTP)@en[[[PUT]]]] や [CODE(HTTP)@en[[[DELETE]]]]
のような状態を変更する[[要求メソッド]]では、並列に動作する別の[[クライアント]]の更新を誤って上書きしてしまう
「[[lost update]]」問題を防ぐために[[条件付き要求]]を使えます [SRC[>>3 1.]]。
]FIG]
[7] 事前条件として記述される資源のメタデータのことを、[[検証子]]といいます [SRC[>>3 2.]]。
* 条件付きヘッダー
[2] 次の[[要求ヘッダー]]は[DFN[[RUBYB[[[条件付き]]]@en[conditional]]]]に分類されています [SRC[>>1]]。
[FIG(list short)[
- [CODE(HTTP)@en[[[If-Match:]]]]
- [CODE(HTTP)@en[[[If-None-Match:]]]]
- [CODE(HTTP)@en[[[If-Modified-Since:]]]]
- [CODE(HTTP)@en[[[If-Unmodified-Since:]]]]
- [CODE(HTTP)@en[[[If-Range:]]]]
]FIG]
;; [11] これらは [[RFC 7232]] では[DFN[[RUBYB[事前条件]@en[precondition]]]]
[SRC[>>10]] ヘッダーと呼ばれています。
* 処理モデル
[45] [[受信者]]である[[キャッシュ]]や[[起源鯖]]は、
[[要求]]を次のように処理しなければ[['''なりません''']] [SRC[>>18, >>29]]。
[FIG(steps)[
= [22] [[要求]]をチェックし、必要があればエラーの[[応答]]を返したり、
[[リダイレクト]]の[[応答]]を返したりします。その場合ここで終わります。 [SRC[>>18]]
= [24] [[要求メソッド]]が[[選択された表現]]の選択や編集に関わるものである場合 (>>27) [SRC[>>18]]、
== [46] [[受信者]]が[[対象資源]]の[[起源鯖]]である場合 [SRC[>>18, >>29]]、
=== [52] [[要求]]に [CODE(HTTP)@en[[[If-Match:]]]] [[ヘッダー]]がある場合 [SRC[>>12, >>29]]、
その評価結果が[[偽]]なら、
==== [50] >>19 の場合は [CODE(HTTP)[[[2xx]]]] を返して終わっても構いません。
==== [51] そうしないなら、 [CODE(HTTP)[[[412]]]] を返して終わります。
=== [53] [[要求]]に [CODE(HTTP)@en[[[If-Match:]]]] [[ヘッダー]]がなく、
[CODE(HTTP)@en[[[If-Unmodified-Since:]]]] [[ヘッダー]]がある場合、 [SRC[>>29, >>25]]
その評価結果が[[偽]]なら、
==== [56] >>19 の場合は [CODE(HTTP)[[[2xx]]]] を返して終わっても構いません。
==== [57] そうしないなら、 [CODE(HTTP)[[[412]]]] を返して終わります。
== [26] [[受信者]]が[[対象資源]]の[[起源鯖]]である場合や[[キャッシュ]]として動作する場合 [SRC[>>18, >>29]]、
=== [48] [[要求]]に [CODE(HTTP)@en[[[If-None-Match:]]]] [[ヘッダー]]がある場合 [SRC[>>21, >>29]]、
その評価結果が[[偽]]なら、
==== [59] [[要求メソッド]]が [CODE(HTTP)@en[[[GET]]]] か [CODE(HTTP)@en[[[HEAD]]]] なら、
[CODE(HTTP)[[[304]]]] を返して終わります。
==== [60] それ以外なら、 [CODE(HTTP)[[[412]]]] を返して終わります。
=== [61] [[要求]]に [CODE(HTTP)@en[[[If-None-Match:]]]] [[ヘッダー]]がなく [SRC[>>29, >>14]]、
[CODE(HTTP)@en[[[If-Modified-Since:]]]] [[ヘッダー]]がある場合、
その評価結果が[[偽]]なら、
==== [64] [[要求メソッド]]が [CODE(HTTP)@en[[[GET]]]] か [CODE(HTTP)@en[[[HEAD]]]] なら、
[CODE(HTTP)[[[304]]]] を返して終わります [SRC[>>29, >>14]]。
=== [55] [[要求]]に [CODE(HTTP)@en[[[If-Range:]]]] [[ヘッダー]]があり、
その評価結果が[[真]]なら、 [SRC[>>28, >>29]]
==== [66] [[要求メソッド]]が [CODE(HTTP)@en[[[GET]]]] なら、
[CODE(HTTP)@en[[[Range:]]]] [[ヘッダー]]があればそれを処理して
[CODE(HTTP)[[[206]]]] を返して終わって構いません。 ([[範囲要求]]を参照。)
= [63] 事前条件は一致したので、[[要求]]の他の指定に従って処理し、結果を返します。
== [31] [[要求メソッド]]が [CODE(HTTP)@en[[[GET]]]] なら、
[CODE(HTTP)@en[[[If-Range:]]]] [[ヘッダー]]がなく
[CODE(HTTP)@en[[[Range:]]]] [[ヘッダー]]があればそれを処理して
[CODE(HTTP)[[[206]]]] を返して終わって構いません。 [SRC[>>28]] ([[範囲要求]]を参照。)
== [33] それ以外なら、 [CODE(HTTP)[[[2xx]]]] を返します。
]FIG]
;; [13] 条件を満たすかどうかの判定については、各[[ヘッダー]]の項を参照してください。
;; [23] >>64 は >>14 ではなぜか [['''SHOULD''']] とされており、 >>29 の
[['''MUST''']] と矛盾します。両方の要件を満たすには、 [['''MUST''']]
と解釈するしかありません。
;; [34] >>66 [CODE(HTTP)@en[[[Range:]]]] の処理は、なぜか [['''MUST''']]
ではなく [['''SHOULD''']] となっています [SRC[>>28]]。 [CODE(HTTP)[[[206]]]]
を実装しないことが認められているので [['''MUST''']] なのかもしれませんが、
詳細不明です。
[27] 事前条件は[[選択された表現]]の選択や編集に関わる[[要求メソッド]]以外では無視する
[SRC[>>18]] とされています。無視するべきメソッドとして [CODE(HTTP)@en[[[CONNECT]]]]、
[CODE(HTTP)@en[[[OPTIONS]]]]、[CODE(HTTP)@en[[[TRACE]]]] が挙げられています [SRC[>>18]] が、
完全なリストはなぜか提供されていません。
[40] [[ヘッダー]]の優先順位の根拠は次のように説明されています [SRC[>>29]]。
[FIG(list)[
- [42] 「[[lost update]]」の条件は[[キャッシュ]]の[[検証]]よりも厳密な要件である
- [43] [[検証]]された[[キャッシュ]]は[[部分応答]]よりも効率的である
- [44] [[実体タグ]]は日時の[[検証子]]よりも正確である
]FIG]
[FIG(corollary)[
[20] [CODE(HTTP)@en[[[If-Match:]]]] や [CODE(HTTP)@en[[[If-Unmodified-Since:]]]]
は[[起源鯖]]のみが処理し、[[キャッシュ]]は無視することになっています [SRC[>>12, >>25]] が、
[CODE(HTTP)@en[[[If-None-Match:]]]] や [CODE(HTTP)@en[[[If-Modified-Since:]]]]
は[[起源鯖]]だけでなく[[キャッシュ]]も処理することになっています。
]FIG]
[41] [CODE(HTTP)@en[[[If-Match:]]]] や [CODE(HTTP)@en[[[If-None-Match:]]]]
や [CODE(HTTP)@en[[[If-Modified-Since:]]]] や [CODE(HTTP)@en[[[If-Unmodified-Since:]]]]
を実装していない場合どう動作するべきか仕様上明確ではありませんが、
実際の[[鯖]]はこれらを無視するようです。 ([CODE(HTTP)[[[412]]]]
や [CODE(HTTP)[[[304]]]] ではありません。)
[16] [[受信者]]は、 [CODE(HTTP)@en[[[If-Modified-Since:]]]] や
[CODE(HTTP)@en[[[If-Unmodified-Since:]]]] が妥当な
[CODE(ABNF)@en[[[HTTP-date]]]] でないとき、これを無視しなければ[['''なりません''']]
[SRC[>>14, >>25]]。
;; [32] [CODE(HTTP)@en[[[If-Match:]]]] や [CODE(HTTP)@en[[[If-None-Match:]]]]
や [CODE(HTTP)@en[[[If-Range:]]]] が構文的に正しくない時にどう処理するべきかは、
なぜか規定がありません。
;; [15] 無視ということは、条件の真偽を判断する以前に存在しないものと扱うのだと思われます。
[30] [CODE(HTTP)@en[[[If-Range:]]]] [[ヘッダー]]は、
[CODE(HTTP)@en[[[Range:]]]] [[ヘッダー]]が含まれていなければ無視しなければ[['''なりません''']]
[SRC[>>29]]。
;; [17] 同じ[[ヘッダー]]が複数ある時にどう処理するべきかはなぜか規定がありません。
[19] >>50、>>56 で [CODE(HTTP)[[[2xx]]]] を返せるのは、状態の変更が[[要求]]されており、
最終的な状態が既に[[対象資源]]の現在の状態に反映されていると[[起源鯖]]が確認できる場合です。
すなわち、以前の[[応答]]が失われたか互換性のある変更が他の[[利用者エージェント]]により行われたかによって[[利用者エージェント]]の[[要求]]が既に成功していたことに気づいていないような場合です。
ただしそのような場合には、同じ[[利用者エージェント]]が直前の[[要求]]を繰り返していると確認できる場合を除き、
[[検証子ヘッダー]]を送っては[['''なりません''']] [SRC[>>12, >>25]]。