Tag: api, rest, rest-api, http, json, web-services, backend, api-design
Livello: intermedio
TL;DR: Best practice per la progettazione di API REST: denominazione risorse, metodi HTTP, codici di stato, paginazione, versionamento e idempotenza.
Usa sostantivi plurali per identificare le risorse e mai verbi negli endpoint (/api/v1/orders).
Sfrutta i metodi HTTP standard: GET per lettura, POST per creazione, PUT per sostituzione completa.
Usa PATCH per aggiornamenti parziali e DELETE per rimozione delle risorse.
Mantieni GET, HEAD, OPTIONS e PUT idempotenti; POST non e' idempotente per definizione.
Ritorna codici di stato HTTP semanticamente corretti per ogni scenario di successo o errore.
Versiona l'API tramite URI path (/api/v1/...) o header custom (Accept: application/vnd.myapi.v1+json).
Implementa paginazione standard tramite query parameter (limit, offset o cursor-based con token).
Fornisci payload di errore strutturati e consistenti su tutti gli endpoint (es. standard RFC 7807).
Supporta il filtraggio e l'ordinamento tramite query parameters espliciti (?status=active&sort=-created_at).
Assicura statelessness: ogni richiesta contiene tutte le informazioni necessarie per essere elaborata.
Q: Qual e' la differenza tra PUT e PATCH in un'API REST?R: PUT sostituisce integralmente la risorsa target con il payload inviato, mentre PATCH applica una modifica parziale solo ai campi specificati nella richiesta.
Q: Come gestisci l'idempotenza nelle chiamate di pagamento o checkout (POST)?R: Implemento un header di idempotenza, come Idempotency-Key, salvando la chiave univoca e la risposta iniziale per restituire lo stesso output in caso di retry duplicati.
Q: Quale codice di stato restituisci quando una risorsa richiesta non esiste?R: Restituisco 404 Not Found corredato da un payload JSON con codice di errore applicativo e messaggio descrittivo.
Q: Quando e' preferibile usare una paginazione a cursore rispetto a limit/offset?R: Scelgo il cursore su dataset grandi o in rapido aggiornamento, poiche' evita problemi di skip/duplicazione di record ed e' piu' efficiente a livello di query database.
Inserire verbi nelle URI (es. /api/getUser, /api/createInvoice) invece di sfruttare i verbi HTTP.
Restituire HTTP 200 OK con un payload contenente { success: false, error: "..." }.
Confondere 401 Unauthorized (mancata autenticazione) con 403 Forbidden (mancanza di permessi).
Dimenticare di validare a fondo il Content-Type e l'Accept header nelle richieste in entrata.
Esporre dettagli interni del database o stack trace nei payload di errore HTTP 500.
Introdurre breaking change sui campi di risposta senza aggiornare la versione dell'API.
// Risposta di errore standard (ispirata a RFC 7807 Problem Details)
{
"type": "https://api.example.com/errors/resource-not-found",
"title": "Resource Not Found",
"status": 404,
"detail": "Customer with ID 42 was not found.",
"instance": "/api/v1/customers/42"
}
HTTP
# Esempio di richiesta di aggiornamento parziale
PATCH /api/v1/customers/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"email": "user@example.com"
}
[ ] Meccanismi di HATEOAS e livelli del Richardson Maturity Model
[ ] Pattern di rate limiting tramite header HTTP (X-RateLimit-Limit, Retry-After)
[ ] Differenze architetturali tra REST, GraphQL e gRPC
[x] Mappatura codici di stato HTTP 2xx, 4xx, 5xx
[x] Regole di naming e convenzioni RESTful