← Tous les articles

Choisir les codes d'erreur HTTP sans masquer la panne réelle

Guide pour distinguer les erreurs 4xx et 5xx via un scénario d'album photo privé afin d'orienter la récupération côté client.

  • rest-api
  • learning-series
Dans cet article

La philosophie de la signalisation d’erreur

Les codes de statut HTTP ne sont pas de simples étiquettes ; ce sont des instructions pour le client. Un 500 Internal Server Error indique que le serveur a échoué à gérer une situation, tandis qu’un code 4xx signale que le client doit modifier sa requête pour réussir. Lorsqu’une API réduit chaque erreur métier à un 500 ou un 400 générique, elle prive le client de la possibilité de récupérer automatiquement.

Mapper les pannes aux codes de statut

400 couvre une requête mal formée et peut aussi servir à la validation selon le contrat ; 422 convient à un contenu bien formé impossible à traiter. 401 indique l’absence de justificatifs d’authentification valides et exige WWW-Authenticate. 403 indique un refus du serveur, sans prouver universellement une authentification réussie. Une politique de confidentialité peut employer 404 pour une ressource inaccessible.

409 signale un conflit avec l’état actuel. Une précondition If-Match non satisfaite donne 412 Precondition Failed, pas systématiquement 409. Un champ de version contrôlé par la logique applicative peut donner 409 selon le contrat.

Exemple concret : Trace de l’album photo

Scénario : Un client tente de modifier une photo dans un album privé. Voici la trace des différents modes de panne et l’action client correspondante.

RequêteÉtat/Condition du ServeurCode StatutDétail En-tête/CorpsAction Client
PATCH /photos/abc-123L’ID abc-123 n’est pas un UUID valide400{"error": "Invalid ID format"}Corriger la syntaxe
PATCH /photos/uuid-1Token expiré401WWW-Authenticate: BearerRafraîchir token/Re-connexion
PATCH /photos/uuid-2User A tente de modifier la photo de User B403 (ou 404){"error": "Access denied"}Cesser les tentatives
PATCH /photos/uuid-3La ressource n’existe pas404{"error": "Photo not found"}Supprimer du cache local
PATCH /photos/uuid-4 + If-MatchETag mismatch412{"error":"Precondition failed"}GET → reconcile → retry
PATCH /photos/uuid-5Légende de 10 000 caractères422{"field": "caption", "msg": "Too long"}Demander de raccourcir
PATCH /photos/uuid-6Timeout connexion base de données500{"error": "Internal error"}Réessayer (backoff exponentiel)

Nuances d’implémentation

Lors de l’implémentation, évitez la tentation d’utiliser un bloc catch (Exception e) unique qui retourne 500. Mappez plutôt des exceptions métier spécifiques à ces codes.

Cas d’échec : La boucle 401/403 Si un client reçoit un 401, il doit tenter de rafraîchir le token. S’il reçoit un 403, il ne doit pas rafraîchir le token, car l’identité est déjà vérifiée ; c’est la permission qui manque. Rafraîchir sur un 403 crée une boucle infinie de requêtes inutiles.

Exercice

Scénario : Vous créez une API de partage de fichiers. Un utilisateur tente de télécharger un fichier dans un dossier. Voici ce qui arrive :

  1. L’ID du dossier est fourni sous forme de chaîne, mais le système attend un entier.
  2. L’utilisateur est connecté, mais le dossier est marqué comme “Lecture seule” pour son groupe.
  3. L’utilisateur tente de télécharger un fichier avec le même nom qu’un fichier déjà existant, et la règle métier interdit les doublons.

Question : Quels codes de statut HTTP doivent être retournés pour ces trois cas, et pourquoi ?

Réponse :

  1. 400 Bad Request : Le type d’entrée est syntaxiquement incorrect pour l’identifiant attendu.
  2. 403 Forbidden : L’utilisateur est authentifié, mais l’action spécifique (écriture) est interdite par les permissions de la ressource.
  3. 409 Conflict : La requête ne peut pas être traitée en raison de l’état actuel de la ressource (conflit de nom de fichier).

Pour approfondir