REST エンドポイントの場合、開発者は多くの場合、更新で新しいレコードを作成するか、既存のレコードのみを変更するかを制御する必要があります。
If-Match HTTP ヘッダーは、データ API ビルダー (DAB) でそのコントロールを提供します。
既定では、DAB は PUT と PATCH を アップサート 操作として扱います。
リソースが存在する場合:更新されます。
存在しない場合は挿入されます。
-
PUT完全なアップサートを→します (リソースを置き換えます)。 -
PATCH増分アップサートを→します (部分的な更新が適用されます)。
-
If-Match: *を追加すると、この動作が更新専用セマンティクスに変更されます。
DAB での If-Match の機能
If-Match は、ワイルドカード値 *でのみサポートされます。
| ヘッダー値 | 行動 |
|---|---|
If-Match: * |
リソースが存在する場合にのみ更新を実行します。見つからない場合→ 404 が見つかりません。 |
If-Match: <any other> |
拒否;400 Bad Request (Etags not supported, use '*')。 |
| (不在) | アップサート動作 (見つからない場合は挿入、それ以外の場合は更新)。 |
動作の概要
- DAB では、レコードごとの ETag やバージョンマッチングは実装されません。
- コンカレンシー トークンは評価されません。
*"存在する必要があります" のみをアサートします。 - GraphQL ではなく REST にのみ適用されます。
- 現在、DELETE 操作では意味がありません。
PUT での If-Match の使用
If-Matchしないと、リソースが存在しないときに PUT が挿入されます (201 Createdが返されます)。
更新のみの例
リクエスト
PUT /api/Books/id/1
If-Match: *
Content-Type: application/json
{
"title": "The Return of the King"
}
成功 (レコードが存在)
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 1,
"title": "The Return of the King"
}
エラー (レコードがありません)
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "No Update could be performed, record not found"
}
Upsert 挿入の例 (If-Match がなく、レコードが存在しませんでした)
リクエスト
PUT /api/Books/id/500
Content-Type: application/json
{
"title": "Inserted via PUT",
"publisher_id": 7
}
[応答]
HTTP/1.1 201 Created
Location: id/500
Content-Type: application/json
{
"id": 500,
"title": "Inserted via PUT",
"publisher_id": 7
}
PATCH での If-Match の使用
PATCH は同様に動作します。
If-Matchしないと、増分アップサートが実行されます。
If-Match: *では、既存の行のみが更新されます。
リクエスト
PATCH /api/Books/id/1
If-Match: *
Content-Type: application/json
{
"title": "The Two Towers"
}
成功時の対応
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 1,
"title": "The Two Towers"
}
見つからない場合の応答
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "No Update could be performed, record not found"
}
If-Match の使用が無効です
*以外の値 (引用符で囲まれた文字列を含む) は拒否されます。
リクエスト
PUT /api/Books/id/1
If-Match: "abc123"
Content-Type: application/json
{
"title": "To Kill a Mockingbird"
}
[応答]
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Etags not supported, use '*'"
}
Review
- upsert (insert-or-update) セマンティクスの
If-Matchを省略します。 - 厳密な更新専用セマンティクスには
If-Match: *を使用します (項目がない場合は 404)。 - 他の値は使用しないでください。 実際の ETag 照合は実装されていません。