インターネットエンジニアリングタスクフォース (IETF) L. Dusseault
Request for Comments: 5789 Linden Lab
カテゴリ: Standards Track J. Snell
ISSN: 2070-1721 2010年3月

HTTP の PATCH メソッド


概要

ハイパーテキスト転送プロトコル (HTTP) を拡張するいくつかのアプリケーションは、リソースの部分的な変更を行う機能を必要とします。既存の HTTP PUT メソッドはドキュメントの完全な置換のみを許可します。本提案は、既存の HTTP リソースを変更するための新しい HTTP メソッド PATCH を追加するものです。

このメモの状態

これはインターネット標準トラックの文書です。

本書はインターネットエンジニアリングタスクフォース (IETF) の成果物です。IETF コミュニティの合意を表しています。公開審査を経てインターネットエンジニアリング運営グループ (IESG) による公開承認を受けています。インターネット標準に関する詳細は RFC 5741 のセクション 2 を参照してください。

本書の現状、訂正情報 (errata)、およびフィードバックの送付方法に関する情報は http://www.rfc-editor.org/info/rfc5789 で入手できます。

Copyright Notice

Copyright (c) 2010 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

1. 導入

本仕様は、新しい HTTP/1.1 のメソッド PATCH(リソースに対して部分的な修正を適用するために使用される)を定義します。参照: [RFC2616]

相互運用性を向上させエラーを防ぐために新しいメソッドが必要です。PUT メソッドは既にリソースを完全な新しいボディで上書きするよう定義されており、部分的変更に再利用することはできません。そうでなければ、プロキシやキャッシュ、さらにはクライアントやサーバが操作の結果について混乱する可能性があります。POST はすでに使用されていますが、パッチ形式のサポートを発見する標準的な方法がないなど、広範な相互運用性を持ちません。PATCH は以前の HTTP 仕様で言及されていましたが、完全には定義されていませんでした。

本書ではキーワード "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", および "OPTIONAL" は [RFC2119] に記載されたとおりに解釈されます。

さらに、本書は [RFC2616] のセクション 2.1 で定義された ABNF 構文を使用します。

2. PATCH メソッド

PATCH メソッドは、要求エンティティ内に記述された変更の集合を Request-URI で識別されるリソースに適用するよう要求します。変更の集合はメディアタイプで識別される「パッチ文書」と呼ばれる形式で表現されます。もし Request-URI が既存のリソースを指していない場合、サーバはパッチ文書の種類(null リソースを論理的に修正できるかどうか)や権限等に応じて、新しいリソースを作成してもよい(MAY)です。

PUT と PATCH の違いは、リクエストに含まれるエンティティをどのように処理して Request-URI で識別されるリソースを修正するかに反映されます。PUT リクエストでは、同梱されたエンティティはオリジンサーバに格納されているリソースの修正版と見なされ、クライアントは格納されたバージョンの置換を要求します。一方 PATCH では、同梱されたエンティティはリソースを新しいバージョンにするための指示の集合を含みます。PATCH メソッドは Request-URI で識別されるリソースに影響を与え、また他のリソースに副作用を及ぼすこと(新しいリソースが作成されたり既存のものが修正されたりすること)もあります。

PATCH は [RFC2616] セクション 9.1 に定義されるとおり、安全でも冪等でもありません。

PATCH リクエストは冪等となるように発行することができ、これにより同一リソースに対する短時間での二つの PATCH リクエスト間の競合による悪影響を防ぐ助けになります。複数の PATCH リクエストからの衝突は、ある種のパッチ形式が既知のベースポイントから動作する必要がある場合に PUT の衝突より危険であり、そうでなければリソースを破損する恐れがあります。この種のパッチ適用を行うクライアントは、リソースがクライアントが最後にアクセスした以降に更新されていればリクエストが失敗するような条件付きリクエストを使用するべきです(SHOULD)。例えば、クライアントは PATCH リクエストの If-Match ヘッダに強い ETag を使用できます。

行末にテキストを追加するログファイルや、衝突しない行をデータベース表に追加するような、既知のベースポイントから動作する必要がないパッチ形式もあります。その場合はクライアントリクエストにおける同様の注意は不要です。

サーバは変更集合全体を原子的に適用し、この操作中に部分的に修正された表現を(例えば GET への応答として)提供してはなりません。パッチ文書全体を正常に適用できない場合、サーバはどの変更も適用してはなりません(MUST NOT)。PATCH の成功と見なす条件は、パッチ文書や修正されるリソースの種類により異なり得ます。例えば一般的な diff ユーティリティはディレクトリ階層内の複数ファイルに適用できるパッチ文書を生成できます。原子性の要件は直接影響を受けるすべてのファイルに対して適用されます。ステータスコードや可能なエラー条件の詳細については "Error Handling"(セクション 2.2)を参照してください。

要求がキャッシュを通過し、Request-URI が現在キャッシュされているエンティティを一つ以上識別する場合、それらのエントリは古くなったものとして扱うべきです(SHOULD)。このメソッドへの応答は、明示的な鮮度情報(Expires ヘッダや "Cache-Control: max-age" ディレクティブなど)と、PATCH 応答本文がリソース表現であることを示す Request-URI に一致する Content-Location ヘッダを含む場合にのみキャッシュ可能です。キャッシュされた PATCH 応答は、その後の GET および HEAD リクエストに応答するためにのみ使用でき、他のメソッド(特に PATCH)に応答するために使用してはなりません。

リクエストに含まれるエンティティ-ヘッダは、同梱されたパッチ文書にのみ適用され、修正されるリソース自体には適用してはなりません。したがって、Content-Language ヘッダがリクエストに存在しても、それはパッチ文書に言語があることを意味するにすぎません。サーバはそのようなヘッダをトレース情報として除いて保存すべきではなく、PUT リクエストで使われるのと同じ方法でそれらのヘッダ値を使用すべきではありません。したがって、本書はヘッダを通じてドキュメントの Content-Type や Content-Language を変更する方法を指定していませんが、パッチ文書を通じてこの目的を達成する仕組みを設計することは可能です。

リソースが PATCH で修正可能である保証はありません。さらに、異なるパッチ文書形式が異なる種類のリソースに適切であり、単一の形式がすべてのリソース型に適切であることは期待されません。したがって、実装がサポートする必要のある単一のデフォルトのパッチ文書形式は存在しません。サーバは受信したパッチ文書が Request-URI で識別されるリソースの種類に適切であることを保証しなければなりません(MUST)。

クライアントはいつ PATCH を PUT より使用するかを選択する必要があります。例えば、パッチ文書のサイズが PUT で使用される新しいリソースデータのサイズより大きい場合は、PATCH の代わりに PUT を使用する方が合理的かもしれません。POST と比較するのはさらに難しく、POST は多様な使われ方をし、サーバが選択すれば PUT や PATCH に類する操作を包含し得ます。操作が Request-URI によって識別されるリソースを予測可能な方法で変更しない場合、PATCH や PUT の代わりに POST を検討すべきです。

2.1. 簡単な PATCH の例

PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100

[description of changes]

この例は、既存リソースに対する仮想的なパッチ文書の使用を示しています。

既存のテキストファイルに対する成功した PATCH 応答:

HTTP/1.1 204 No Content
Content-Location: /file.txt
ETag: "e0023aa4f"

204 応答コードが使われているのは、応答がメッセージ本文を持たないためです(200 コードの応答は本文を持つ可能性があります)。他の成功コードが使われることもあり得ます。

さらに、ETag レスポンスヘッダは、Content-Location レスポンスヘッダで示されるように、PATCH を適用して作成されたエンティティ(http://www.example.com/file.txt)の ETag を含みます。

2.2. エラー処理

PATCH リクエストが失敗する既知の条件がいくつかあります。

不正なパッチ文書:
サーバがクライアントから提供されたパッチ文書が正しくフォーマットされていないと判断した場合、400 (Bad Request) を返すべきです(SHOULD)。不正なフォーマットの定義は選択されたパッチ文書形式によって異なります。
サポートされないパッチ文書:
クライアントがサーバが Request-URI で識別するリソースに対してサポートしていないパッチ文書形式を送信した場合、415 (Unsupported Media Type) 応答で指定できます。そのような応答には、クライアントにサポートされるパッチ文書のメディアタイプを通知するために、セクション 3.1 に記載された Accept-Patch レスポンスヘッダを含めるべきです(SHOULD)。
処理不能な要求:
サーバがパッチ文書を理解し、文法が有効に見えるが処理できない場合、422 (Unprocessable Entity) 応答で指定できます(参照: [RFC4918] セクション 11.2)。これは例えば、よく形成された XML ドキュメントを無効にしてしまうような変更を試みた場合などが含まれます。より具体的なエラー(例: "Conflicting State")がこのステータスコードで通知されることもありますが、より具体的なエラーの方が一般に有用です。
リソースが見つからない:
選択したパッチ文書が存在しないリソースに適用できない場合、404 (Not Found) で指定できます。
矛盾する状態:
リクエストがリソースの状態を考慮すると適用できない場合、409 (Conflict) を使用できます。例えば、クライアントが構造的な変更を適用しようとしたが、想定される構造が存在しない場合(XML では要素 'foo' を 'bar' に変更する指定があっても 'foo' が存在しない等)が該当します。
競合する変更:
クライアントが If-Match や If-Unmodified-Since ヘッダで事前条件を定義し、その事前条件が失敗した場合、412 (Precondition Failed) が最も有用です。ただし、リクエストに事前条件がない場合、この応答は意味をなさないことに注意してください。事前条件が定義されていない場合にサーバが競合する可能性のある変更を検出したときは、409 (Conflict) を返すことができます。
同時変更:
PATCH の一部の適用ではサーバが受信順にリクエストを処理する必要がある場合があります。そのような制約下で、同一リソースに対する同時のリクエストをキューできない場合、サーバは 409 (Conflict) 応答でこれを示すことが有用です。

409 Conflict 応答はクライアントに対して比較的一貫した情報を提供します。アプリケーションやパッチ形式の性質によっては、クライアントがそのままリクエストを再送できる場合(例: ログファイルに行を追加する命令)、リソース内容を取得してパッチを再計算する必要がある場合、あるいは操作が失敗してユーザによる確認が必要になる場合があります。

適切な状況では他の HTTP ステータスコードも使用できます。

エラー応答のエンティティ本文には、クライアントに対してエラーの性質を伝えるのに十分な情報を含めるべきです(SHOULD)。応答エンティティの content-type は実装により異なり得ます。

3. OPTIONS におけるサポートの告知

サーバは、HTTP/1.1 で定義された "Allow" OPTIONS レスポンスヘッダの許可されたメソッド一覧に PATCH を追加することで、PATCH のサポートを告知できます。Accept-Patch ヘッダが存在しなくても、PATCH メソッドは "Allow" ヘッダに表示され得ます。その場合、許可されるパッチ文書の一覧は告知されません。

3.1. Accept-Patch ヘッダ

本仕様は、サーバが受け入れるパッチ文書形式を指定するための新しいレスポンスヘッダ Accept-Patch を導入します。Accept-Patch は PATCH メソッドをサポートする任意のリソースの OPTIONS 応答に現れるべきです(SHOULD)。任意のメソッドへの応答に Accept-Patch ヘッダが存在することは、暗黙のうちに Request-URI で識別されるリソースで PATCH が許可されていることを示します。Accept-Patch ヘッダに特定のパッチ文書形式が含まれている場合、その特定の形式が Request-URI で識別されるリソースで許可されていることを示します。

Accept-Patch = "Accept-Patch" ":" 1#media-type 

Accept-Patch ヘッダは、[RFC2616] セクション 3.7 で定義されるメディアタイプのカンマ区切りリスト(オプションのパラメータ付き)を指定します。

例:

Accept-Patch: text/example;charset=utf-8

3.2. OPTIONS 要求と応答の例

[request]

OPTIONS /example/buddies.xml HTTP/1.1
Host: www.example.com

[response]

HTTP/1.1 200 OK
Allow: GET, PUT, POST, OPTIONS, HEAD, DELETE, PATCH
Accept-Patch: application/example, text/example

これらの例は、一般的に PATCH をサポートするサーバを、二つの仮想的なパッチ文書形式を使って示しています。

4. IANA に関する考慮事項

4.1. Accept-Patch レスポンスヘッダ

Accept-Patch レスポンスヘッダは永続的レジストリに追加されました(参照: [RFC3864])。

ヘッダフィールド名:
Accept-Patch
適用プロトコル:
HTTP
Author/Change controller:
IETF
仕様文書:
本仕様

5. セキュリティに関する考慮事項

PATCH のセキュリティ考慮事項は PUT のそれとほぼ同一です(参照: [RFC2616] セクション 9.6)。これにはリクエストの認可(アクセス制御や認証による)や、転送エラーや偶発的な上書きによるデータの破損が含まれます。PUT に使用されるメカニズムは PATCH にも利用できます。以下は PATCH に特に適用される考慮点です。

パッチされたドキュメントは、全体を上書きするドキュメントよりも破損しやすい可能性がありますが、これらの懸念は If-Match リクエストヘッダを使った ETag による条件付きリクエストなどのメカニズムで対処できます(セクション 2 を参照)。PATCH リクエストが失敗した場合、クライアントは GET リクエストを発行してリソースの状態を確認できます。基盤となるトランスポートチャネルが失敗した場合やタイムアウトが発生し PATCH 応答を受信できなかった場合は、クライアントは GET を発行して要求が適用されたかを確認する必要が生じるかもしれません。クライアントは GET 要求がキャッシュをバイパスするように、HTTP 仕様で記述された機構(例えば [RFC2616] のセクション 13.1.6)を使用することを検討してもよいでしょう。

HTTP 中間体が PUT/POST リクエストや GET 応答の本文をチェックしてウイルスを検出しようとすることがあります。PATCH メソッドは、元のドキュメントやパッチ文書のどちらもウイルスではない場合でも、結果がウイルスとなり得るため、そのような監視を複雑にします。このセキュリティ上の考慮は、バイトレンジダウンロードやパッチ文書のダウンロード、圧縮ファイルのアップロードなどにより既に導入されている問題と本質的に異なりません。

個々のパッチ文書には、パッチされるリソースの種類に依存して異なる固有のセキュリティ考慮事項が存在します。例えば、バイナリ資源をパッチする場合の考慮は XML 文書をパッチする場合と異なります。サーバは悪意のあるクライアントが PATCH を使って過大なサーバリソース(CPU、ディスク I/O など)を消費できないよう十分な予防措置を講じる必要があります(MUST)。

6. 参考文献

6.1. 規範的参照

[RFC2119]
Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14, RFC 2119, March 1997.
[RFC2616]
Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, “Hypertext Transfer Protocol -- HTTP/1.1”, RFC 2616, June 1999.
[RFC3864]
Klyne, G., Nottingham, M., and J. Mogul, “Registration Procedures for Message Header Fields”, BCP 90, RFC 3864, September 2004.

6.2. 情報的参照

[RFC4918]
Dusseault, L., “HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)”, RFC 4918, June 2007.

Appendix A. 謝辞

PATCH は新しい概念ではなく、最初は Roy Fielding と Henrik Frystyk によって書かれた HTTP 1.1 の草案に登場し、また RFC 2068 のセクション 19.6.1.1 にも現れています。

Adam Roach、Chris Sharp、Julian Reschke、Geoff Clemm、Scott Lawrence、Jeffrey Mogul、Roy Fielding、Greg Stein、Jim Luther、Alex Rousskov、Jamie Lokier、Joe Hildebrand、Mark Nottingham、Michael Balloni、Cyrus Daboo、Brian Carpenter、John Klensin、Eliot Lear、SM、Bernie Hoeneisen に対して、本書のレビューと助言に感謝します。特に Julian Reschke は繰り返しレビューを行い、多くの有用な提案をし、本書の公開に重要な貢献をしました。

著者の連絡先

Lisa Dusseault
Linden Lab
945 Battery Street
San Francisco, CA 94111
USA
Email: lisa.dusseault@gmail.com
James M. Snell
Email: jasnell@gmail.com
URI: http://www.snellspace.com