HTTPQUERY
日本語

PATCH

使い方

PATCH リクエストは、既存のリソースをどのように変更するかを記述した一連の指示を送信します。リソース全体を置き換える PUT とは異なり、PATCH は指定されたフィールドやプロパティのみを変更します。

リクエストボディには、サーバーが理解できる形式のパッチドキュメントが含まれます。Content-Type ヘッダーがパッチ形式を示します。サーバーレスポンスの Accept-Patch ヘッダーは、サポートするパッチ形式を公表します。

注意

PATCH は非推奨ではありません。このメソッドは 2010 年に標準化され、HTTP セマンティクスの現役の一部であり続けています。PATCH が他のメソッドより後から追加されたことや、一部の古いフレームワークがネイティブサポートを欠いていることから混乱が生じています。

注意

PATCH には冪等性の保証がありません。同じパッチを2回適用すると異なる結果になることがあります(例:リストへの2回の追加)。同じリソースへの同時パッチは、条件付きリクエスト(If-Unmodified-Since または If-Match)がなければ競合のリスクを伴います。

一般的なパッチ形式

JSON Patch は、変更を操作の順序付き配列として表現します。操作には add、remove、replace、move、copy、test があります。

Content-Type: application/json-patch+json

[
  {"op":"replace","path":"/email",
   "value":"alice@example.re"},
  {"op":"add","path":"/verified","value":true}
]

JSON Merge Patch はより単純なアプローチをとります。パッチドキュメントはターゲットリソースの構造を反映します。パッチに存在するフィールドが既存の値を上書きします。フィールドを null に設定すると、そのフィールドは削除されます。

Content-Type: application/merge-patch+json

{"email":"alice@example.re","nickname":null}

原子性

サーバーはパッチドキュメント内のすべての変更を単一の原子的な操作として適用します。いずれかの指示が失敗した場合、パッチ全体が拒否され、リソースは変更されないままになります。

注意

PATCH リクエストには副作用があり、冪等であることは保証されません。「リストに追加する」操作に対して同一のパッチを2回連続で適用すると、1回だけ適用した場合とは異なる結果になります。

JSON Merge Patch

クライアントが JSON Merge Patch 形式を使ってユーザー 42 のメールアドレスを更新します。サーバーは変更を適用し、更新後のリソースとともに 200 OK を返します。

リクエスト

PATCH /users/42 HTTP/1.1
Host: api.example.re
Content-Type: application/merge-patch+json
Content-Length: 28

{"email":"alice@example.re"}

レスポンス

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 51

{"id":42,"name":"Alice","email":"alice@example.re"}

JSON Patch

クライアントが設定リソースに2つの操作を適用します。debug フラグの置き換えと、新しいログレベルフィールドの追加です。サーバーは 204 No Content で確認します。

リクエスト

PATCH /config/app HTTP/1.1
Host: api.example.re
Content-Type: application/json-patch+json
Content-Length: 102

[
  {"op":"replace","path":"/debug","value":false},
  {"op":"add","path":"/logLevel","value":"warn"}
]

レスポンス

HTTP/1.1 204 No Content

条件付きパッチ

If-Unmodified-Since を使った条件付きリクエストは、他のクライアントによってすでに変更されたリソースの変更を防ぎます。指定されたタイムスタンプより後にリソースが変更されていた場合、サーバーは 412 Precondition Failed を返します。

リクエスト

PATCH /docs/report.json HTTP/1.1
Host: api.example.re
Content-Type: application/merge-patch+json
If-Unmodified-Since: Mon, 01 Jan 2024 12:00:00 GMT
Content-Length: 21

{"status":"reviewed"}

レスポンス

HTTP/1.1 412 Precondition Failed
Content-Length: 0

CORS

クロスオリジンの PATCH リクエストは常に CORS プリフライトを発生させます。ブラウザはまず OPTIONS リクエストを送信し、サーバーがターゲットリソースに対する PATCH を許可しているかを確認します。

PATCH と PUT の比較

PATCH は変更分のみを送信するため、大きなリソースに対してリクエストが小さくなり帯域効率に優れます。PUT は変更されたフィールドの数にかかわらず、毎回完全な表現を送信します。

PUT は冪等です。同じ PUT リクエストを2回送信しても、サーバーの状態は同じになります。PATCH は冪等であることが保証されません。リストへの追加のような操作は、適用するたびに異なる結果を生むためです。

既存のリソースの特定のフィールドを更新する場合は PATCH を使います。リソース全体を新しい表現で置き換える場合は PUT を使います。

PATCH と POST の比較

PATCH は既知の URI にある既存のリソースを変更します。POST は新しいリソースを作成するか、サーバー側の処理を起動します。

PATCH は JSON Patch や JSON Merge Patch といった定義済みのパッチセマンティクスを使用します。POST はセマンティクスを完全にサーバーに委ね、リクエストボディの形式を規定しません。