Pengembangan Web

HTTP 202 Accepted untuk API Jangka Panjang - Kembalikan Operation, Bukan Janji Keberhasilan

HTTP 202 Accepted untuk API Jangka Panjang - Kembalikan Operation, Bukan Janji Keberhasilan

Seorang client meminta API membuat laporan berukuran besar. Pekerjaan itu mungkin memerlukan beberapa menit, sehingga mempertahankan satu koneksi HTTP tetap terbuka cukup rapuh. Memberikan respons secepatnya terdengar masuk akal, tetapi apa yang bisa dikatakan respons tersebut dengan jujur? Jika responsnya 200 OK, laporan terkesan sudah selesai. Jika responsnya 202 Accepted, bagian sulitnya hanya berpindah: client masih perlu mengetahui apakah pekerjaan berhasil, gagal, atau tidak pernah dimulai.

202 berguna justru karena hanya memberikan janji yang terbatas. Status ini bukan jalan pintas untuk mengatakan “server mungkin akan mengurusnya.” API asynchronous yang dapat diandalkan memerlukan operation resource yang dapat diamati di sekitar status code tersebut, lengkap dengan state yang jelas, informasi kegagalan, access control, dan lifecycle yang dapat dipahami client.

Apa yang sebenarnya dinyatakan oleh 202

RFC 9110 mendefinisikan 202 Accepted sebagai request yang telah diterima untuk diproses, tetapi pemrosesannya belum selesai. Pekerjaan tersebut mungkin nantinya ditolak atau bahkan tidak pernah dijalankan. Respons ini sengaja bersifat noncommittal, tidak memberikan komitmen atas hasil akhir.

Kata terakhir itu adalah bagian pentingnya. Kelas sukses 2xx tidak menjadikan 202 sebagai bukti bahwa hasil bisnis yang diminta telah berhasil. Status ini menyatakan bahwa server menerima request ke dalam proses lanjutan. RFC tersebut juga mencatat bahwa HTTP tidak memiliki fasilitas untuk mengirim ulang status code dari asynchronous operation itu. Server tidak dapat secara retroaktif mengganti 202 awal dengan 201 Created atau 500 Internal Server Error.

Spesifikasi yang sama menyatakan bahwa representasi respons sebaiknya menjelaskan status request saat ini dan menunjuk ke, atau menyertakan, status monitor. Ini adalah panduan, bukan wire format universal. HTTP mendefinisikan arti 202; API tetap harus mendefinisikan cara client mengamati semua hal yang terjadi setelahnya.

Pisahkan request, operation, dan result

Ada tiga identitas yang mudah tercampur:

  1. Request yang dikirim meminta server memulai pekerjaan.
  2. Operation resource mewakili satu eksekusi tertentu beserta state-nya yang berubah.
  3. Result resource adalah laporan, export, akun, atau domain object lain yang dihasilkan jika operation berhasil.

Operation bukan sekadar detail implementasi. Ia adalah pegangan yang tahan lama bagi client untuk menghadapi ketidakpastian. Pertukaran ilustratifnya dapat terlihat seperti ini:

POST /reports HTTP/1.1
Host: api.example.test
Content-Type: application/json

{"from":"2026-10-01","to":"2026-10-31"}

HTTP/1.1 202 Accepted
Location: /operations/op_7f31
Content-Type: application/json

{
  "id": "op_7f31",
  "status": "pending",
  "status_url": "/operations/op_7f31"
}

Nama field tersebut merupakan pilihan aplikasi, sedangkan Location adalah pola yang umum, bukan kewajiban untuk setiap respons 202. Hal yang penting adalah kontraknya mengidentifikasi satu tempat stabil bagi client yang berwenang untuk menanyakan apa yang terjadi.

Jadikan operation sebagai state machine kecil

Pesan teks longgar seperti “masih dikerjakan” sulit diotomatisasi. Sekumpulan state terdokumentasi yang terbatas akan lebih jelas. API kecil dapat memakai pending, running, succeeded, failed, dan canceled. Nama lain juga dapat dipakai, tetapi client perlu mengetahui state mana yang terminal dan mana yang masih dapat berubah.

{
  "id": "op_7f31",
  "status": "running",
  "created_at": "2026-11-07T00:12:00Z",
  "updated_at": "2026-11-07T00:12:08Z",
  "progress": null,
  "result_url": null,
  "error": null
}

progress sebaiknya bersifat opsional. Sebagian job memiliki unit yang dapat diukur; job lain menghabiskan sebagian besar waktunya dalam satu tahap yang sulit diprediksi. Persentase rekaan lebih buruk daripada tidak ada persentase karena mengubah ketidakpastian menjadi presisi yang menyesatkan. Timestamp, state saat ini, dan deskripsi singkat mungkin sudah cukup.

Panduan long-running operation dari Google menggunakan pemisahan umum yang sama: operation memiliki metadata ketika aktif dan pada akhirnya memuat response atau error. Schema persisnya khusus untuk Google, bukan standar HTTP generik, tetapi pembedaan itu dapat diterapkan secara luas. Penyelesaian memerlukan hasil yang machine-readable, bukan sekadar hilangnya kata “pending.”

Validasi dahulu, lalu terima secara durable

Asynchronous processing bukan alasan untuk menunda validasi. Authentication, authorization, media type, syntax dasar, field wajib, dan business precondition yang murah untuk diperiksa sebaiknya divalidasi sebelum mengembalikan 202. Jika server sudah mengetahui bahwa request tidak valid atau dilarang, server sebaiknya langsung mengembalikan error yang sesuai, bukan membuat operation yang pasti gagal.

Acceptance juga memerlukan durability boundary yang bermakna. Jika API mengembalikan 202 lalu kehilangan task yang hanya tersimpan di memory saat process restart, status code itu menyiratkan keyakinan yang lebih besar daripada kemampuan implementasinya. Aplikasi kecil dapat melakukan commit terhadap operation row dan queue record di database sebelum menjawab. Sistem lain dapat mengandalkan message broker yang durable. Teknologinya bersifat sekunder; respons sebaiknya dikirim setelah aplikasi menyimpan cukup informasi untuk melanjutkan pekerjaan atau memperlihatkan kegagalannya.

Hal ini tidak menjamin hasil akhir. Worker masih dapat gagal, dependency dapat menolak operation, atau administrator dapat membatalkannya. Durable admission hanya membuat janji awal tetap jujur: aplikasi dapat mempertanggungjawabkan operation yang diterima alih-alih melupakannya tanpa jejak.

Polling adalah kontrak, bukan tight loop

Client dapat melakukan GET ke operation resource hingga mencapai terminal state. API sebaiknya mendokumentasikan strategi polling yang wajar. Tanpa panduan, banyak client akan melakukan polling secepat loop mereka berjalan, menambah beban tanpa membuat pekerjaan selesai lebih cepat.

Pola asynchronous request-reply dari Microsoft menyarankan pengembalian lokasi status dan menggunakan Retry-After sebagai petunjuk polling. Itu merupakan panduan desain yang berguna, tetapi Retry-After bukan komponen khusus yang wajib ada pada setiap 202. Apakah nilainya berupa jeda, apakah client menerapkan backoff, dan apakah estimasinya berubah harus menjadi bagian dari kontrak API yang terdokumentasi.

Respons status juga memerlukan cache policy yang jelas. Shared cache atau browser cache yang menyajikan representasi pending lama dapat membuat operation yang sudah selesai tampak macet. API dapat mencegah penyimpanan yang tidak tepat atau mendefinisikan validator dan revalidation dengan sengaja. Policy yang tepat bergantung pada apakah data operation bersifat privat, seberapa sering datanya berubah, dan apakah caching benar-benar memberi manfaat.

Representasikan penyelesaian tanpa menulis ulang riwayat

Ketika laporan sudah siap, operation resource dapat tetap menjadi representasi 200 OK biasa dengan status: succeeded dan tautan menuju hasil:

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

{
  "id": "op_7f31",
  "status": "succeeded",
  "result_url": "/reports/report_91c2",
  "error": null
}

Desain lain yang terdokumentasi dapat mengembalikan 303 See Other dari status endpoint dan menaruh result URI di Location. Microsoft menjelaskan varian tersebut karena 303 mengarahkan client untuk mengambil resource yang berbeda dengan GET. Ini adalah pilihan, bukan akhir yang diwajibkan untuk semua asynchronous API. Mempertahankan representasi final operation sering berguna ketika client membutuhkan completion metadata atau audit trail.

Kegagalan mengikuti prinsip yang sama. 202 awal tetap benar secara historis: request telah diterima. Representasi operation berikutnya mencatat bahwa eksekusi gagal dan menyediakan error object yang stabil dan terbatas. API sebaiknya membedakan kegagalan bisnis atau pemrosesan yang terminal dari gangguan sementara saat membaca status endpoint. Keduanya merupakan peristiwa berbeda dan mungkin membutuhkan perilaku client yang berbeda.

Rancang kegagalan, authorization, dan expiry bersama-sama

Operation URL dapat mengungkap nama pelanggan, parameter export, detail error, atau tautan menuju file yang dibuat. Identifier yang sulit ditebak berguna, tetapi bukan authorization. Setiap request untuk status, hasil, dan pembatalan harus diperiksa terhadap caller dan tenant pemilik operation. Log sebaiknya tidak menyalin data request sensitif hanya karena job berjalan di background.

Operation record juga tidak boleh hidup selamanya tanpa disengaja. Kontrak harus menyatakan berapa lama operation yang selesai dan hasil yang dibuat tetap tersedia, serta apa yang diterima client setelah expiry. AIP-151 secara eksplisit mengizinkan operation resource kedaluwarsa, sedangkan pola Microsoft juga menyarankan retention policy. Keduanya tidak memberikan durasi universal untuk API kecil. Biaya penyimpanan, kebutuhan audit, privasi, dan rentang pemulihan client yang realistis menentukan pilihan tersebut.

Cancellation membutuhkan kehati-hatian serupa. API dapat menyediakan DELETE /operations/op_7f31 atau tindakan pembatalan lain, tetapi cancellation request bukan bukti bahwa setiap side effect telah dibalikkan. Worker mungkin sudah melewati batas yang tidak dapat dibatalkan. Kontrak harus menjelaskan apakah cancellation bersifat best-effort, state mana yang menerimanya, dan apakah pekerjaan parsial membutuhkan compensation.

Prefer dapat menyatakan preferensi client, bukan perintah

RFC 7240 mendefinisikan Prefer: respond-async agar client dapat menyatakan bahwa ia lebih memilih asynchronous handling. RFC tersebut juga mendefinisikan preferensi wait yang opsional. Server boleh mengabaikan preferensi, dan RFC sengaja membiarkan mekanisme untuk memperoleh hasil akhir sebagai detail yang bergantung pada implementasi.

Header ini berguna ketika endpoint dapat memilih antara response synchronous yang cepat dan operation resource. Header tersebut tidak diperlukan ketika kontrak API selalu memproses operation secara asynchronous, dan tidak memperbaiki API yang tidak memiliki semantik status dan kegagalan. Preference negotiation dan operation design menyelesaikan masalah yang berbeda.

Kapan 202 bukan alat yang tepat

Operation resource menambah write, traffic polling, cleanup, aturan authorization, state di sisi client, dan monitoring. Jika server dapat menyelesaikan request dengan cepat dan andal, final response biasa lebih sederhana dan lebih informatif. Sifat nonblocking pada JavaScript tidak dengan sendirinya membenarkan penggunaan 202 di server; client dapat menunggu respons HTTP biasa tanpa membekukan user interface.

Polling juga tidak ideal untuk setiap workload. Server-Sent Events, WebSockets, webhooks, atau message-oriented interface mungkin lebih sesuai bagi client yang membutuhkan update berlatensi rendah atau memproses banyak hasil. Alternatif tersebut memiliki biaya koneksi, delivery, dan security masing-masing. Pilihannya bukan “modern versus lama”, melainkan observation model mana yang dapat didukung kedua sisi secara jujur.

Checklist peninjauan ringkas

  • Tolak kegagalan authentication, authorization, syntax, dan validation yang sudah diketahui sebelum mengembalikan 202.
  • Simpan operation state secukupnya agar dapat bertahan melewati request process sebelum menyatakan acceptance.
  • Berikan status resource yang stabil dan terotorisasi untuk setiap operation.
  • Dokumentasikan state nonterminal dan terminal, termasuk failure dan cancellation.
  • Jangan menciptakan nilai progress ketika kemajuannya tidak dapat diukur.
  • Tentukan panduan polling, cache behavior, dan rate limit.
  • Buat hasil atau error akhirnya machine-readable.
  • Tentukan retention, expiry, dan perilaku setelah record dihapus.
  • Uji worker crash, pengiriman duplikat, initial response yang hilang, status authorization, terminal failure, dan cancellation race.
  • Gunakan 202 hanya ketika pemisahan acceptance dari completion sepadan dengan tambahan protocol state.

Kesimpulan

202 Accepted bukan janji keberhasilan. Status ini adalah cara jujur untuk mengatakan bahwa tanggung jawab telah berpindah melampaui pertukaran HTTP saat ini. Kejujuran itu hanya bertahan jika API memberi client operation identity yang durable dan jalur yang jelas menuju success, failure, cancellation, atau expiry.

Untuk API kecil, desainnya dapat tetap sederhana: lakukan validasi dahulu, catat operation secara durable, kembalikan tautan status, tampilkan state machine yang terbatas, dan pertahankan hasil terminal selama periode yang terdokumentasi. Pertanyaan yang tersisa seharusnya bukan “apakah background worker mungkin sudah berjalan?” Pertanyaan itu harus dapat dijawab oleh operation resource.

References