-
Notifications
You must be signed in to change notification settings - Fork 4
/
215.txt
272 lines (198 loc) · 13.7 KB
/
215.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
[3] [DFN[[CODE(HTTP)@en[[[PATCH]]]]]] は、
[[差分]]を指定して[[資源]]の一部を更新される[[要求メソッド]]です。
;; 全体の更新を行う [CODE(HTTP)@en[[[PUT]]]] とは異なり、一部分のみを更新します。
* 仕様書
[REFS[
- [6] '''[CITE@en[RFC 5789 - PATCH Method for HTTP]] ([TIME[2014-09-22 15:11:26 +09:00]] 版) <http://tools.ietf.org/html/rfc5789>'''
- [39] [CITE[RFC Errata Report]] ([TIME[2014-12-03 22:58:08 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=5789>
]REFS]
* 意味
[12] [CODE(HTTP)@en[[[PATCH]]]] [[メソッド]]は、
[[要求]]の [[payload body]] に記述した変更の集合を[[対象資源]]に適用することを求めるものです
[SRC[>>6]]。
[11] [[冪等メソッド]]でも[[安全メソッド]]でもありません [SRC[>>6]]。
* パッチ文書
[7] 変更の内容を記述した[[文書]]を[RUBYB[[[パッチ文書]]]@en[patch document]]といいます
[SRC[>>6]]。[[パッチ文書]]の[[MIME型]]は特に限定されておらず、任意のものを使えます。
実装が強制されている[[MIME型]]もありません。
[21] [CODE(HTTP)@en[[[PATCH]]]] [[要求]]の[[HTTPヘッダー]]はすべて[[パッチ文書]]に適用されるものであって、
[[パッチ]]による変更を表しているものではありません。従って、(記録目的等を除いて)
[[鯖]]には[[蓄積]]される[['''べきではありません''']]。 [SRC[>>6]]
;; [22] [[ヘッダー]]も変更したい場合は、それが可能な[[MIME型]]を利用して[[パッチ文書]]を記述するしかありません。
;; [38] これも [CODE(HTTP)@en[[[PUT]]]] [[要求]]との違いです。
[27] [[鯖]]は、[[パッチ文書]]の書式が正しくないときは [CODE(HTTP)[[[400]]]] を返す[['''べきです''']]。
「書式が正しくない」は[[パッチ文書]]の[[MIME型]]の定義によります。 [SRC[>>6]]
[28] [[鯖]]は、[[パッチ文書]]の[[MIME型]]に未対応の時は [CODE(HTTP)[[[415]]]] を返す[['''べきです''']]。
その[[応答]]には [CODE(HTTP)@en[[[Accept-Patch]]]] [[頭欄]]も含める[['''べきです''']]。
[SRC[>>6]]
[29] [[鯖]]は、[[パッチ文書]]を理解できて、しかし処理できない場合、
[CODE(HTTP)@en[[[422]]]] を返す[['''べきです''']]。 例えば、[[XML文書]]が適用対象で、
パッチの適用によって[[整形式]]でなくなる場合には [CODE(HTTP)@en[[[422]]]] を返すことができます。
[SRC[>>6]]
[40] [[鯖]]は、 [CODE(MIME)@en[[[application/json]]]] や [CODE(MIME)@en[[[application/xml]]]]
のような一般的で [CODE(HTTP)@en[[[PATCH]]]] における意味を定義していない
[[MIME型]]を[[パッチ文書]]として使えると考える[['''べきではありません''']] [SRC[>>39]]。
[41] [CODE(HTTP)@en[[[PATCH]]]] で使うことを想定したと明記されている[[差分]]の記述形式には、
次のものがあります。
[FIG(short list)[
- [[JSON Patch]]
- [[JSON Merge Patch]]
]FIG]
* 処理
[8] [[鯖]]は、[[対象資源]]が存在しなければ、新たに作成しても[['''構いません''']]し、
[CODE(HTTP)[[[404]]]] を返すなどしても構いません。また、
副作用的に[[対象資源]]以外を変更しても構いません。[SRC[>>6]]
[EG[
[9] 一般的な [[diff]] コマンドは複数のファイルを変更できます [SRC[>>6]]。
]EG]
[16] [[鯖]]は操作を[RUBY[[[原子的]]][アトミック]@en[atomic]]に行わなければ[['''なりません''']]。
複数の[[資源]]に変更が及ぶ場合であっても、すべて変更されるかすべて変更されないかのいずれかでなければなりません。
操作の途中に[[要求]]があっても、部分的に変更されたものを[[応答]]として返してはなりません。
[SRC[>>6]]
[32] 誤りを表す[[応答]]の [[payload body]] は、誤りを説明する十分な情報を含んだものである[['''べきです''']]。
その[[MIME型]]は特に規定されていません。 [SRC[>>6]]
** キャッシュ
[17] [[要求URL]]が同じ[[キャッシュ項目]]があれば、[[腐敗]]したものとする[['''べきです''']]
[SRC[>>6]]。
[18] [[応答]]は、[[新鮮度]] ([CODE(HTTP)@en[[[Expires:]]]] や
[CODE(HTTP)@en[[[Cache-Control:]] [[max-age]]]]) が明示されており、
かつ [CODE(HTTP)@en[[[Content-Location:]]]] が[[対象URL]]
と一致する ([[応答]]の [[payload body]] が[[資源]]の[[表現]]である)
場合には、[[キャッシュ可能]]です [SRC[>>6]]。
;; [19] [CODE(HTTP)@en[[[POST]]]] [[メソッド]]も [CODE(HTTP)@en[[[PATCH]]]]
と同じ意味で[[キャッシュ可能]]です。 [CODE(HTTP)@en[[[GET]]]] や
[CODE(HTTP)@en[[[HEAD]]]] が[[キャッシュ可能]]であるというのとは若干意味が異なります。
[20] [CODE(HTTP)@en[[[PATCH]]]] への[[応答]]は
[CODE(HTTP)@en[[[GET]]]] や [CODE(HTTP)@en[[[HEAD]]]]
に対してのみ使うことができます。その他の[[メソッド]]には使っては[['''なりません''']]。
[SRC[>>6]]
;; [37] [CODE(HTTP)@en[[[PATCH]]]] [[メソッド]]に対する[[応答]]にも使えません。
* 衝突
[13] [[パッチ]]を当てる操作は一般には[[冪等]]ではありませんし、順序に依存します。
複数の[[パッチ]]を同時に当てようとすると、意図しない編集結果になることもあります。
[14] ある基準点に対して差分を記述する形の場合は、
変更元の [CODE(HTTP)@en[[[ETag]]]] を [CODE(HTTP)@en[[[If-Match]]]] [[頭欄]]に指定するなどして[[条件付要求]]として
[CODE(HTTP)@en[[[PATCH]]]] [[メソッド]]を発行すれば、意図しない更新は避けることができます。
そのような操作を行う[[クライアント]]は[[条件付要求]]を使う[['''べきです''']]。 [SRC[>>6]]
[15] [[ログ]]などでどんどん追記していくような形で差分が記述される場合はそのような衝突は起こらないので、
配慮は不要です。 [SRC[>>6]]
[30] [[鯖]]は衝突により変更を適用できないときは [CODE(HTTP)[[[409]]]]
を返すことができます。 [SRC[>>6]]
* 歴史
** RFC 2068 における定義
[4] [CODE(HTTP)@en[[[PATCH]]]] [[メソッド]]は公式には [[RFC 2068]]
ではじめて定義されました。ただし完全な規定ではなく、参考として挙げられているに過ぎませんでした。
[31] [[RFC 5789]] の定義は雰囲気こそこの [[RFC 2068]] の定義と似ていますが、
基本的に互換性はありません。
[FIG(quote)[
[FIGCAPTION[
[36] RFC 2068 (HTTP/1.1) 19.6.1.1 PATCH
]FIGCAPTION]
> The PATCH method is similar to PUT except that the entity contains a
list of differences between the original version of the resource
identified by the Request-URI and the desired content of the resource
after the PATCH action has been applied. The list of differences is
in a format defined by the media type of the entity (e.g.,
"application/diff") and MUST include sufficient information to allow
the server to recreate the changes necessary to convert the original
version of the resource to the desired version.
[CODE(HTTP)[PATCH]] 方式は [CODE(HTTP)[[[PUT]]]] 方式と似ていますが、
実体は [CODE(ABNF)[[[Request-URI]]]] で識別される資源の元の版と資源の
[CODE(HTTP)[PATCH]] 動作を適用した後に望まれる内容の差異の一覧を含みます。
差異の一覧は実体の媒体型 (たとえば [CODE(MIME)[[[application/diff]]]])
で定義された書式であり、サーバーが資源の元の版から望む版に変換するのに必要な変更を再生成するのに十分な情報を含まなければ'''なりません'''。
> If the request passes through a cache and the Request-URI identifies
a currently cached entity, that entity MUST be removed from the
cache. Responses to this method are not cachable.
要求が[[キャッシュ]]を通じて渡され、 [CODE(ABNF)[Request-URI]]
が現在キャッシュされている実体を識別するなら、
その実体はキャッシュから削除しなければ'''なりません'''。
この方式への応答は[[キャッシュ可能]]ではありません。
> The actual method for determining how the patched resource is placed,
and what happens to its predecessor, is defined entirely by the
origin server. If the original version of the resource being patched
included a Content-Version header field, the request entity MUST
include a Derived-From header field corresponding to the value of the
original Content-Version header field. Applications are encouraged to
use these fields for constructing versioning relationships and
resolving version conflicts.
継ぎ当てした資源をどう配置するのか、以前のものがどうなるのかを決定する実際の方法は、
完全に起源サーバーが定義します。資源の元の版を
[CODE(HTTP)[[[Content-Version]]]] 頭欄を含めて継ぎ当てする場合は、要求実体は
元の [CODE(HTTP)[Content-Version]] 頭欄の値に対応する
[CODE(HTTP)[[[Derived-From]]]] 頭欄を含めなければ'''なりません'''。
[[応用]]は版付け関係を構築し、版衝突を解決するためにこれらの欄を使うことを推奨します。
> PATCH requests must obey the message transmission requirements set
out in section 8.2.
[CODE(HTTP)[PATCH]] 要求は、8.2節のメッセージ転送要件に従わなければなりません。
> Caches that implement PATCH should invalidate cached responses as
defined in section 13.10 for PUT.
[CODE(HTTP)[PATCH]] を実装する[[キャッシュ]]は、
13.10節で [CODE(HTTP)[[[PUT]]]] について定義されているようにキャッシュ応答を無効化するべきです。
]FIG]
** RFC 2616 における削除
[5] [[RFC 2068]] の改訂版である [[RFC 2616]] では、 [[RFC 2068]] 中のあまり実装されていない機能は省かれており [SRC[>>34]]、
[CODE(HTTP)@en[[[PATCH]]]] [[メソッド]]も説明されていませんでした。
;; [35] 使われていないとは述べられていますが、[[廃止]]とはされていませんでした。
[REFS[
- [34] [CITE@en[RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2014-09-07 04:14:53 +09:00]] 版) <http://tools.ietf.org/html/rfc2616#page-175>
]REFS]
* 例
** パッチをあてる例
[26] 単純な差分適用の例 [SRC[>>6]]
[PRE(HTTP example code)[
PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100
[・・・差分・・・]
]PRE]
... という要求に対して、
[PRE(HTTP example code)[
HTTP/1.1 204 No Content
Content-Location: /file.txt
ETag: "e0023aa4f"
]PRE]
- [[要求]]は差分の適用元の [CODE(HTTP)@en[[[ETag]]]] を [CODE(HTTP)@en[[[If-Match]]]] に入れて[[条件付要求]]とし、意図しない適用を防いでいます。
- [[応答]]は成功したことだけを [CODE(HTTP)@en[[[204]]]] で伝えています。変更後の [CODE(HTTP)@en[[[ETag]]]] も知らせています。
* 関連
** [CODE(HTTP)@en[PUT]] との関係
[10] [CODE(HTTP)@en[[[PUT]]]] [[要求]]は、 [[payload body]] が[[鯖]]に蓄積されているものの修正版そのものであり、
蓄積されているものをまるごと置き換えることを求めています。
一方 [CODE(HTTP)@en[[[PATCH]]]] [[要求]]は、 [[payload body]]
が修正版を得るためにどう変更するべきかの指示となっています。 [SRC[>>6]]
[23] [CODE(HTTP)@en[[[PATCH]]]] の方がかえって [CODE(HTTP)@en[[[PUT]]]]
よりサイズが大きくなってしまうような場合もあるので、[[クライアント]]はどちらが適当か考える必要があります。
[SRC[>>6]]
** [CODE(HTTP)@en[[[POST]]]] との関係
[24] [CODE(HTTP)@en[[[POST]]]] はより一般的で、「なんでもあり」なので、
[CODE(HTTP)@en[[[PATCH]]]] 相当の操作を [CODE(HTTP)@en[[[POST]]]] で行うこともできますし、
実際よく行われています。
[25] 変更したい対象が [CODE(HTTP)@en[[[Request-URI]]]] から明確に予測可能でない場合は、
[CODE(HTTP)@en[[[PATCH]]]] よりも [CODE(HTTP)@en[[[POST]]]] を使うのが適切です。 [SRC[>>6]]
* メモ
[1]
[CITE@en-US[snellspace.com » Blog Archive » Beyond APP - Partial updates]] ([CODE[2007-06-10 13:10:13 +09:00]] 版) <http://www.snellspace.com/wp/?p=683>
([[名無しさん]] [WEAK[2007-06-10 04:13:12 +00:00]])
[2]
[CITE@en-US[snellspace.com » Blog Archive » PATCH Update]] ([CODE[2007-07-27 23:41:24 +09:00]] 版) <http://www.snellspace.com/wp/?p=710>
([[名無しさん]] [WEAK[2007-07-27 14:44:20 +00:00]])
[423] [CITE[tus resumable upload protocol]]
( ([TIME[2014-06-23 00:14:49 +09:00]] 版))
<http://tus.io/protocols/resumable-upload.html#5-3-2>
[424] [CITE@ja[Performance Tips - Gmail API — Google Developers]]
( ([TIME[2014-07-14 21:46:41 +09:00]] 版))
<https://developers.google.com/gmail/api/guides/performance>
[33] [[Web API]] などで [CODE(HTTP)@en[[[PATCH]]]] [[メソッド]]を
[CODE(HTTP)@en[[[POST]]]] [[メソッド]]の代わりに使うことが最近増えていますが、
どちらを選ぶかは宗教的な判断なので、特にこだわりがなければ広く利用されている
[CODE(HTTP)@en[[[POST]]]] にしておくのが無難でしょう。
[FIG(quote)[
[FIGCAPTION[
[42] [CITE@en[GitHub API v3]]
([TIME[2015-02-05 07:24:20 +09:00]] 版)
<https://developer.github.com/v3/>
]FIGCAPTION]
> PATCH is a relatively new and uncommon HTTP verb, so resource endpoints also accept POST requests.
]FIG]