Note dal lavoro · Backend
API sicure da ripetere: idempotenza e retry
Una richiesta HTTP può fallire dopo aver funzionato: il server ha creato l’ordine, ma la risposta si è persa e il client non lo sa. Se riprova, rischia di crearne due. Per questo, nelle API che modificano dati, conviene progettare i retry fin dall’inizio.
Quali metodi sono già sicuri
Per definizione GET, PUT e DELETE sono idempotenti: ripeterli produce lo stesso stato finale. POST no: ogni invio può creare una nuova risorsa. È lì che serve un meccanismo in più.
L’header Idempotency-Key
Una convenzione molto diffusa (la usano, tra gli altri, le API di pagamento) è far generare al client una chiave univoca per ogni operazione logica e inviarla in un header Idempotency-Key. Il server la memorizza insieme al risultato.
- Prima richiesta: il server esegue l’operazione e salva chiave, impronta del contenuto e risposta.
- Stessa chiave e stesso contenuto: restituisce la risposta salvata, senza rieseguire nulla.
- Stessa chiave e contenuto diverso: è un errore del client, da rifiutare (per esempio con
422o409). - Chiavi scadute dopo un tempo ragionevole (ore o giorni): non servono per sempre.
Le trappole
- Richieste simultanee con la stessa chiave: serve un vincolo univoco nel database o un lock, non solo un controllo «esiste già?» seguito da un inserimento.
- Salva anche gli errori definitivi (validazione), così un retry non cambia l’esito.
- Gli effetti collaterali esterni (email, pagamenti) devono stare dietro la stessa protezione, altrimenti il retry li ripete.
In Laravel
Un middleware legge l’header, cerca la chiave in una tabella con indice univoco su (utente, chiave) e, se la trova, restituisce la risposta salvata. Se non la trova, esegue la richiesta e salva il risultato. I job in coda vanno trattati allo stesso modo: scritti in modo che eseguirli due volte non faccia danni.
Il principio generale: dai per scontato che ogni richiesta possa arrivare due volte, e fai in modo che la seconda sia innocua.