Поделиться через


Использование заголовка HTTP If-Match в операциях PUT и PATCH

Для конечных точек REST разработчики часто хотят контролировать, создают ли обновления новые записи или изменяют только существующие. Заголовок HTTP предоставляет этот элемент управления в построителе If-Match API данных (DAB).

По умолчанию DAB обрабатывает PUT и PATCH как операции upsert :

  • Если ресурс существует: он обновляется.

  • Если он не существует: он вставлен.

    • PUT → полный upsert (заменяет ресурс).
    • PATCH → добавочного upsert (применяет частичное обновление).

Добавление If-Match: * изменений в семантику только для обновления.

Что If-Match делает в DAB

If-Match поддерживается только с подстановочным значением *.

Значение заголовка Поведение
If-Match: * Выполните обновление только в том случае, если ресурс существует; Значение , если отсутствует → 404 Not Found.
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этого он выполняет добавочную upsert. При этом 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 '*'"
}

Отзыв

  • Опустить If-Match семантику upsert (insert-or-update).
  • Используется If-Match: * для строгой семантики только для обновления (404, если элемент отсутствует).
  • Не используйте другое значение. Сопоставление real ETag не реализовано.