Les erreurs avec problem+json
Le code de statut dit qu'il y a une erreur. Le body doit dire laquelle, et comment la corriger. Plutôt que d'inventer un format par API, il existe un standard : application/problem+json.
Le format
HTTP/1.1 409 Conflict
Content-Type: application/problem+json
{
"type": "https://api-ritif.example/problems/order-not-cancellable",
"title": "La commande ne peut plus être annulée",
"status": 409,
"detail": "La commande 42 est en préparation. Le shaker tourne déjà.",
"instance": "/v1/orders/42"
}
| Champ | Rôle |
|---|---|
type |
Une URI qui identifie le type d'erreur. Idéalement, une page de documentation qui l'explique. Par défaut : about:blank. |
title |
Un résumé court, le même pour toutes les erreurs de ce type. |
status |
Le code de statut HTTP, répété pour faciliter la lecture. |
detail |
L'explication propre à cette occurrence, lisible par un humain. |
instance |
Une URI qui identifie cette occurrence précise (la ressource concernée, ou un identifiant de log). |
Tous les champs sont facultatifs, mais type, title et status sont un minimum raisonnable.
Les extensions
On peut ajouter ses propres champs. Le cas le plus courant : les erreurs de validation, avec la liste des champs en faute.
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
{
"type": "https://api-ritif.example/problems/validation-error",
"title": "Données invalides",
"status": 422,
"detail": "La requête contient 2 erreurs.",
"errors": [
{"field": "rating", "message": "doit être compris entre 1 et 5"},
{"field": "comment", "message": "ne doit pas dépasser 500 caractères"}
]
}
Le client peut afficher chaque message sous le bon champ du formulaire, sans parser une phrase.
Les bonnes pratiques
- Le même format pour toutes les erreurs de l'API, y compris les
404et les500. - Un
detailqui dit quoi corriger : « la note doit être comprise entre 1 et 5 », pas « erreur de validation ». - Jamais d'informations internes dans une erreur.
Ceci n'est pas un message d'erreur, c'est une fuite d'informations :{"error": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'prix' in /var/www/api/models/Cocktail.php line 42"}
Un attaquant y apprend votre base de données, votre langage, votre arborescence et le nom de vos colonnes. Loggez le détail côté serveur, renvoyez un message neutre au client.