web-dev-qa-db-ja.com

RESTで部分更新(PATCH)をサポートする方法

大きなリソースがあり、そこから部分的な情報を更新したいので、リソースの部分的な更新を実装したいです。次のリンクを通過しましたが、
HTTP POSTまたはPATCHメソッドを使用するかどうかを判断できます。

RESTのHTTP MODIFY動詞?

RESTfulな部分更新を送信する方法は?

http://jacobian.org/writing/rest-worst-practices/

https://github.com/archiloque/rest-client/issues/79

http://tools.ietf.org/html/draft-dusseault-http-patch-16

http://greenbytes.de/tech/webdav/draft-dusseault-http-patch-06.html

http://jasonsirota.com/rest-partial-updates-use-post-put-or-patch

http://bitworking.org/news/296/How-To-Do-RESTful-Partial-Updates

https://github.com/dharmafly/jsonpatch.js

これに対する有効な解決策を提案してください。

26
prashant

RFC5789( http://tools.ietf.org/html/rfc5789 )によると、これはまさにPATCHの目的です。

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

PATCHとPUTの違いは次のとおりです。

PUTリクエストとPATCHリクエストの違いは、サーバーが囲まれたエンティティを処理してRequest-URIで識別されるリソースを変更する方法に反映されます。 PUT要求では、囲まれたエンティティはOriginサーバーに格納されているリソースの変更バージョンと見なされ、クライアントは格納されているバージョンの置き換えを要求しています。ただし、PATCHを使用すると、同封のエンティティには、現在Originサーバーに存在するリソースを変更して新しいバージョンを生成する方法を説明する一連の指示が含まれます。

POSTの制限についても説明します。

PUTメソッドは、リソースを完全に新しい本体で上書きするようにすでに定義されており、部分的な変更を行うために再利用することはできません。そうしないと、プロキシとキャッシュ、さらにはクライアントとサーバーでさえ、操作の結果に関して混乱する可能性があります。 POSTはすでに使用されていますが、幅広い相互運用性はありません(たとえば、パッチ形式のサポートを見つける標準的な方法はありません)[...]

RFCを読んで自分で決めることをお勧めしますが、私にはこれはかなり明確に思えます。PATCH要求は部分的な更新として処理する必要があります。 (注:PUTとは異なり、べき等ではありません。)

編集:コメントでEugeneが指摘したように、PATCHリクエストは"neither safe nor idempotent as defined by [RFC2616]"、それらはそうすることができます:

PATCH要求は、べき等になるように発行できます。これは、同じリソース上の2つのPATCH要求が同じ時間枠で衝突することによる悪い結果を防ぐのにも役立ちます。複数のPATCH要求からの衝突は、一部のパッチ形式が既知のベースポイントから動作する必要があるため、PUT衝突よりも危険な場合があります。そうしないと、リソースが破損します。この種のパッチアプリケーションを使用するクライアントは、クライアントが最後にリソースにアクセスしてからリソースが更新された場合にリクエストが失敗するように、条件付きリクエストを使用する必要があります。たとえば、クライアントはPATCHリクエストのIf-Matchヘッダーで強力なETag [RFC2616]を使用できます。

92

RFC-7386「jsonmergePATCH」で説明されているようなメソッドPATCHを使用する必要があります。

例えば。 「a」の値を変更し、次のようなリソースで「f」を削除する場合:

   {
     "a": "b",
     "c": {
       "d": "e",
       "f": "g"
     }
   }

以下を送信することでこれを達成できます。

       PATCH /target HTTP/1.1
       Host: example.org
       Content-Type: application/merge-patch+json

       {
         "a":"z",
         "c": {
           "f": null
         }
       }
0
TechnoPriest