Menggunakan Header HTTP If-Match dalam operasi PUT dan PATCH

Untuk titik akhir REST, pengembang sering menginginkan kontrol atas apakah pembaruan membuat rekaman baru atau hanya memodifikasi yang sudah ada. Header If-Match HTTP menyediakan kontrol tersebut di penyusun API Data (DAB).

Secara default, DAB memperlakukan PUT dan PATCH sebagai operasi upsert :

  • Jika sumber daya ada: DAB memperbaruinya.

  • Jika tidak ada: DAB menyisipkannya.

    • PUT → upsert penuh (menggantikan sumber daya).
    • PATCH → upsert inkremental (menerapkan pembaruan parsial).

If-Match: * Menambahkan perubahan perilaku ini ke semantik khusus pembaruan.

Apa yang If-Match lakukan di DAB

If-Match hanya didukung dengan nilai *kartubebas .

Nilai Header Perilaku
If-Match: * Lakukan pembaruan hanya jika sumber daya ada; jika hilang → 404 Tidak Ditemukan.
If-Match: <any other> Ditolak; 400 Permintaan Buruk (Etags not supported, use '*').
(Tidak ada) Perilaku upsert (sisipkan jika tidak ditemukan, jika tidak, perbarui).

Gambaran umum perilaku

  • DAB tidak menerapkan ETag per rekaman atau pencocokan versi.
  • Tidak ada token konkurensi yang dievaluasi. * hanya menegaskan "harus ada."
  • Hanya berlaku untuk REST, bukan GraphQL.
  • Saat ini tidak bermakna untuk operasi DELETE.

Menggunakan If-Match dengan PUT

Tanpa If-Match, PUT menyisipkan ketika sumber daya tidak ada (mengembalikan 201 Created).

Contoh khusus pembaruan

Penting

Karena PUT melakukan penggantian penuh, isi permintaan harus menyertakan semua kolom yang tidak dapat diubah ke null. Menghilangkan kolom yang diperlukan menyebabkan 400 Bad Request kesalahan database, bahkan ketika If-Match: * ada. Gunakan PATCH alih-alih PUT jika Anda hanya ingin mengirim subset bidang.

Permintaan

PUT /api/Books/id/1
If-Match: *
Content-Type: application/json

{
  "title": "The Return of the King",
  "publisher_id": 7
}

Berhasil (rekaman ada)

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

{
  "id": 1,
  "title": "The Return of the King",
  "publisher_id": 7
}

Kegagalan (rekaman hilang)

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "No Update could be performed, record not found"
}

Contoh sisipkan upsert (tidak ada If-Match dan rekaman yang tidak ada)

Permintaan

PUT /api/Books/id/500
Content-Type: application/json

{
  "title": "Inserted via PUT",
  "publisher_id": 7
}

Jawaban

HTTP/1.1 201 Created
Location: id/500
Content-Type: application/json

{
  "id": 500,
  "title": "Inserted via PUT",
  "publisher_id": 7
}

Menggunakan If-Match dengan PATCH

PATCH bertempur sama. Tanpa If-Match, ia melakukan upsert inkremental. Dengan If-Match: *, ini hanya memperbarui baris yang ada.

Permintaan

PATCH /api/Books/id/1
If-Match: *
Content-Type: application/json

{
  "title": "The Two Towers"
}

Respons saat Berhasil

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

{
  "id": 1,
  "title": "The Two Towers"
}

Respons ketika Tidak ditemukan

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "No Update could be performed, record not found"
}

Penggunaan If-Match Tidak Valid

Nilai apa pun selain * (termasuk string yang dikutip) ditolak.

Permintaan

PUT /api/Books/id/1
If-Match: "abc123"
Content-Type: application/json

{
  "title": "To Kill a Mockingbird"
}

Jawaban

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "Etags not supported, use '*'"
}

Tinjauan

  • Hilangkan If-Match untuk semantik upsert (insert-or-update).
  • Gunakan If-Match: * untuk semantik khusus pembaruan yang ketat (404 jika item hilang).
  • Jangan gunakan nilai lain. Pencocokan ETag nyata tidak diimplementasikan.

Nota

Fungsionalitas Pembuat API Data 2.0 yang dijelaskan di bagian ini saat ini dalam pratinjau dan mungkin berubah sebelum ketersediaan umum. Untuk informasi selengkapnya, lihat Apa yang baru dalam versi 2.0.