Pendahuluan: Memenuhi Kontrak API Idempoten dengan Pendekatan Go
Kontrak API idempoten memastikan bahwa permintaan yang sama bisa diproses ulang tanpa efek samping yang tidak diinginkan. Di Go, kita perlu menggabungkan otentikasi token yang valid, pengecekan idempotensi, dan retry/webhook yang terkontrol agar kontrak itu terpenuhi. Dalam artikel ini disorot langkah praktis untuk membangun endpoint tersebut, lengkap dengan potongan kode, diagram alur, dan langkah verifikasi produksi.
Fokusnya bukan sekadar teori; kita akan melihat cara menyusun middleware otentikasi, menyimpan status idempoten, serta menangani retry otomatis dan webhook dengan observabilitas.
Menyusun Otentikasi dan Validasi Token yang Aman
Langkah pertama adalah memastikan setiap request membawa token yang bisa diverifikasi tanpa menimbulkan overhead berlebih. Gunakan middleware untuk mengekstrak header Authorization, memeriksa signing key, dan menambahkan informasi identitas ke konteks request.
Contoh middleware minimal:
func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ") if token == "" || !validateToken(token) { http.Error(w, "unauthorized", http.StatusUnauthorized) return } ctx := context.WithValue(r.Context(), "userID", extractUserID(token)) next.ServeHTTP(w, r.WithContext(ctx)) }) }Penting untuk memisahkan validasi token (misal memeriksa HMAC signature atau JWK) dari logika bisnis. Bila validasi gagal, hentikan eksekusi sejak awal supaya sistem tidak membuat perubahan apa pun.
Endpoint Idempoten di Go: Menandai dan Menyimpan Kunci Permintaan
Setelah otentikasi berhasil, kita periksa apakah permintaan sudah pernah diproses. Bagian kunci di sini adalah komponen penyimpanan status idempoten (misalnya Redis atau database SQL) dengan TTL pendek agar tidak menumpuk.
Contoh handler dengan pengecekan idempoten (menggunakan store sederhana):
func idempotentHandler(store IdempotentStore) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { key := r.Header.Get("Idempotency-Key") if key == "" { http.Error(w, "missing idempotency key", http.StatusBadRequest) return } if store.Exists(key) { resp := store.GetResponse(key) w.Header().Set("Content-Type", "application/json") w.Write(resp) return } result := processBusinessLogic(r.Context()) store.SaveResponse(key, result) w.Header().Set("Content-Type", "application/json") w.Write(result) }}Penyimpanan respons memungkinkan retry berikutnya mengembalikan hasil yang sama tanpa mengeksekusi logika berat. Pastikan struktur processBusinessLogic tidak memiliki efek sekunder yang tidak terlindungi oleh transaksi.
Retry dan Webhook Idempoten: Menjamin Konsistensi Data
Retry otomatis sering digunakan pada client atau queue. Untuk menjaga idempoten, sertakan header yang sama (Idempotency-Key) saat retry dilakukan. Pada sisi webhook, tandai setiap penerimaan dengan status dan respons sebelumnya.
Beberapa prinsip:
- Retry client: Gunakan exponential backoff dan hanya retry apabila respons bukan 2xx atau kesalahan jaringan.
- Webhook: Simpan log penerimaan per
Idempotency-Key, balas 200/409 tergantung status. - Pemisahan job: Jika webhook memicu job asinkron, queue job harus memeriksa ulang idempotent key sebelum memproses.
Karena kita menyimpan hasil respons, sistem bisa membedakan apakah webhook berikutnya cuma repeat yang sah atau ada nilai baru yang perlu ditangani.
Diagram Alur Permintaan Idempoten
Diagram sederhana membantu tim melihat jalur otentikasi hingga penyimpanan respons:
Client ---> [Header Authorization + Idempotency-Key] ---> API Gateway ---> Middleware Auth ---> Handler Idempoten ---> Store (Redis/SQL)Pada diagram tersebut, middleware memiliki tanggung jawab utama menjaga token valid, sedangkan handler bertanggung jawab mencatat respons pertama kali.
Langkah Verifikasi dan Observabilitas sebelum Produksi
Sebelum deployment, tim produksi perlu:
- Uji validasi token: Kirim request dengan token kadaluwarsa, rusak, dan valid untuk memastikan middleware memberikan respons konsisten.
- Uji idempotensi: Kirim request identik dua kali dan cek bahwa logika bisnis hanya dipanggil sekali dan respons kedua adalah hasil cache.
- Monitor retry: Siapkan metrik retry rate, waktu tunggu, dan kegagalan untuk melihat apakah backend menerima header idempoten.
- Webhook observability: Logging request idempotency key, respons, dan status delivery untuk memudahkan debugging.
Catatan umum debugging: jika retry tetap memicu logika bisnis, periksa 1) apakah Idempotency-Key tidak berubah 2) apakah store memiliki TTL terlalu pendek 3) apakah sistem memproses request sebelum penyimpanan respons selesai.
Dengan pendekatan ini, tim backend dapat merancang endpoint Go yang mematuhi kontrak API idempoten sekaligus menjaga keamanan token dan mekanisme retry yang dapat dipercaya.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!