Menjawab Kebutuhan Kontrak API Webhook Gambar

Kontrak API Webhook Gambar harus menuntaskan dua masalah sekaligus: mendeteksi payload yang terkorupsi (seperti JPEG regresi) dan menyampaikan status kegagalan tanpa menyebabkan loop tak terbatas. Dengan menata validasi header, checksum, metadata minimal, serta mekanisme fallback dan retry idempotent, tim backend bisa memastikan konsumen dapat menangani kegagalan tanpa kehilangan visibilitas.

Pada bagian berikut, kita langsung membedah elemen-elemen kontrak yang mengembalikan payload sehat, mendeteksi artefak, dan memberi sinyal kegagalan yang terkontrol.

Validasi Payload dan Header Dasar

Webhook gambar harus menolak payload yang jelas-jelas tidak valid pada lapisan pertama. Validasi awal meliputi pemeriksaan header HTTP, panjang payload, dan tanda signature yang disepakati.

Verifikasi MIME dan Content-Length

MIME type harus konsisten dengan jenis gambar yang dikirim, misalnya image/jpeg. Header Content-Length membantu menentukan apakah payload dikirim utuh. Jika panjang bervariasi dan tidak sesuai dengan metadata JPEG, segera tolak dengan status 400 dan log detail panjang yang diharapkan vs aktual.

Gunakan middleware di gateway untuk menolak request tanpa header MIME yang tepat. Contoh pola validasi sederhana dalam pseudo-code:

if request.headers['Content-Type'] not in allowed_types:
    reject(400, "Unsupported MIME type")
if not is_length_within_bounds(request.headers['Content-Length']):
    reject(400, "Length mismatch")

Log detail ini juga membantu tim pengirim menyadari apakah proses upload mereka memotong payload.

Checksum dan Metadata Minimum

Checksum (misalnya SHA-256) yang dihitung sebelum pengiriman dan dikirim dalam X-Image-Checksum membantu memverifikasi integritas byte. Kontrak wajib mencantumkan proses perhitungan checksum dan menjelaskan gaya collision-resistance yang digunakan, agar konsumen tidak mengandalkan nilai checksum yang mudah dipalsukan.

Selain itu, tentukan metadata minimal seperti dimensi (width, height) dan warna utama agar konsumen bisa melakukan validasi ringan sebelum menulis ke penyimpanan. Jika metadata tidak ada atau tidak sesuai format, webhook harus menolak dengan kode 422.

Contoh validasi metadata di endpoint konsumen:

required_meta = ['width', 'height', 'colorProfile']
if not all(key in payload_meta for key in required_meta):
    reject(422, "Missing metadata fields")
if payload_meta['width'] <= 0:
    reject(422, "Invalid dimension")

Menetapkan metadata minimal membantu mencegah payload JPEG regresi yang mungkin tidak memiliki header eksif lengkap.

Deteksi JPEG Regresi dan Mekanisme Fallback

Untuk mencegah artefak JPEG seperti yang dijelaskan oleh projek Bad JPEG, kontrak perlu menambahkan pemeriksaan struktur JPEG, bukan hanya MIME type.

Pemeriksaan Byte dan Struktur JPEG

Setelah checksum dan metadata valid, lakukan pemeriksaan isi: pastikan JPEG memiliki marker 0xFFD8 diawal dan 0xFFD9 di akhir. Gunakan parser ringan untuk memastikan urutan segment tidak melanggar struktur dasar, misalnya tidak ada segment 0xFF yang diikuti nilai tidak valid.

Jika parser menemukan anomali, webhook harus menganggap payload tidak valid. Daripada langsung menolak secara permanen, tempatkan payload ke antrian fallback untuk inspect manual atau reprocessing.

Mekanisme Fallback & Retry Idempotent

Ketika payload ditandai bermasalah, sistem harus:

  • Menolak dengan 4xx untuk pemberitahuan segera (misalnya 422).
  • Mencatat payload dalam storage sementara dengan label suspect untuk analisis.
  • Mengaktifkan mekanisme retry yang idempotent dengan header seperti X-Webhook-Id agar pengirim dapat meresend tanpa menggandakan resource.

Mekanisme retry idempotent memerlukan:

  • Idempotency key yang dikenali di konsumen.
  • Pencatatan status retry (diterima, ditolak, dalam pemeriksaan) di storage.

Jika payload yang sama diterima ulang, konsumen bisa memeriksa status idempotency untuk mencegah pemrosesan ganda serta menunda penerimaan sampai analisis fallback selesai.

Fallback juga bisa menyertakan worker asynchronous yang meng-update status setelah pemeriksaan manual, sehingga pengirim tahu kapan bisa mencoba lagi.

Sinyal Kegagalan dan Pencegahan Loop

Sinyal kegagalan harus konservatif agar pengirim tidak tertipu dan memicu loop retry terus menerus.

Saran kontrak:

  • Tetapkan header respons seperti X-Webhook-Error-Code dan X-Webhook-Error-Detail.
  • Gunakan status 429 atau 5xx hanya ketika sistem sedang overload; sertakan Retry-After.
  • Jika payload rusak secara permanen (checksum mismatch atau JPEG invalid), kirimkan 422 tanpa header Retry-After untuk menghindari loop.

Kasus lain: jika payload perlu ditinjau, balas dengan 202 dan header X-Webhook-Pending, lalu beri tahu pengirim lewat webhook callback lain setelah review selesai.

Di sisi pengirim, kontrak harus mendokumentasikan bahwa retry otomatis hanya boleh dilakukan jika kode 429 atau 5xx. Kode 4xx yang tetap harus dihentikan setelah log pertama.

Contoh Alur Kontrak Webhook

Berikut contoh JSON respons validasi yang bisa disediakan konsumen saat mendeteksi masalah:

{
  "status": "rejected",
  "code": "jpeg_structure",
  "detail": "Marker 0xFFDA tidak ditemukan",
  "checksum": "sha256:abc123",
  "retryable": false
}

Parameter retryable memberi sinyal kepada pengirim apakah retry otomatis diperbolehkan. Jika false, pengirim harus menghentikan retry dan memicu alarm manual.

Untuk fallback review, status bisa berubah menjadi pending lalu accepted setelah validasi manual selesai, dengan webhook callback terpisah kepada produsen.

Kesimpulan

Kontrak API Webhook Gambar yang tahan terhadap JPEG regresi menggabungkan validasi header, checksum, metadata minimal, pemeriksaan struktur, serta mekanisme fallback dan sinyal kegagalan terkontrol. Dengan menyusun kontrak semacam ini, tim backend membuat webhook menjadi komunikatif, dapat diandalkan, dan siap menghadapi artefak gambar yang tidak terduga.