go.idempotency_key
Correctness
Medium
Detects state-modifying HTTP endpoints without idempotency key handling.
Why It Matters
Section titled “Why It Matters”Without idempotency keys:
- Duplicate operations - Retries create duplicate records
- Double charges - Payment retries charge multiple times
- Data inconsistency - Same request processed multiple times
Example
Section titled “Example”// ❌ Before (no idempotency)func createOrder(w http.ResponseWriter, r *http.Request) { order := parseOrder(r) db.Create(&order) // Duplicate on retry!}// ✅ After (with idempotency key)func createOrder(w http.ResponseWriter, r *http.Request) { idempotencyKey := r.Header.Get("Idempotency-Key") if idempotencyKey == "" { http.Error(w, "Idempotency-Key required", 400) return }
// Check if already processed if result, ok := cache.Get(idempotencyKey); ok { json.NewEncoder(w).Encode(result) return }
order := parseOrder(r) db.Create(&order)
cache.Set(idempotencyKey, order, 24*time.Hour) json.NewEncoder(w).Encode(order)}What Unfault Detects
Section titled “What Unfault Detects”- POST/PUT handlers without idempotency key checks
- Payment processing without idempotency
- Order creation without duplicate protection
Auto-Fix
Section titled “Auto-Fix”Unfault generates idempotency middleware:
func IdempotencyMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" || r.Method == "PUT" { key := r.Header.Get("Idempotency-Key") // Check/store key... } next.ServeHTTP(w, r) })}