在 PUT 和 PATCH作中使用 If-Match HTTP 标头

对于 REST 终结点,开发人员通常希望控制更新是创建新记录还是仅修改现有记录。 If-Match HTTP 标头在数据 API 生成器(DAB)中提供该控件。

默认情况下,DAB 将PUTPATCH作为更新插入作处理:

  • 如果资源存在:它已更新。

  • 如果不存在,则插入它。

    • PUT →完整插入(替换资源)。
    • PATCH →增量更新插入(应用部分更新)。

添加 If-Match: * 此行为以仅更新语义。

DAB 中的 If-Match 用途

If-Match 仅支持通配符值 *

标头值 行为
If-Match: * 仅当资源存在时执行更新;如果找不到→ 404,则为 。
If-Match: <any other> 拒绝;400 错误请求 (Etags not supported, use '*')。
(缺席) Upsert 行为(如果未找到插入,则为更新)。

行为概述

  • DAB 不实现每条记录 ETag 或版本匹配。
  • 不会评估并发令牌。 * 仅断言“必须存在”。
  • 仅适用于 REST,不适用于 GraphQL。
  • 目前对 DELETE作没有意义。

将 If-Match 与 PUT 配合使用

如果没有 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
}

将 If-Match 与 PATCH 配合使用

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

  • 省略 If-Match upsert (insert-or-update) 语义。
  • 用于 If-Match: * 严格的仅更新语义(如果缺少该项的话为 404)。
  • 不要使用任何其他值。 未实现真正的 ETag 匹配。