Codes HTTP qui vous piquent vraiment — 301 vs 302, 401 vs 403, et le champ de 5xx
Pas un dictionnaire. Un guide ciblé sur les codes d'état HTTP qui causent des bugs dans les environnements de production — le redirige incorrect qui est maintenant en cache indéfiniment, le malentendu entre 401 et 403 qui révèle votre logique d'authentification, le 429 sans Retry-After, et la confusion entre 503 et 5-04 qui vous pousse à déboguer la mauvaise couche.
Vous avez envoyé une redirection de mauvaise nature. Tous les navigateurs qui l'ont déjà rencontrée ont maintenant stocké cette redirection de façon permanente. La seule solution est d'attendre l'expiration du cache ou de demander aux utilisateurs de vider leur historique de navigateur. C'est un code 301.
Ce n'est pas un dictionnaire de codes d'état — il en existe déjà plusieurs. C'est le guide que vous voulez après avoir lu le tableau et avoir tout de même envoyé le mauvais code. Nous passons en revue les cas qui provoquent des bugs réels : des caches permanents quand vous vouliez des redirections temporaires, des erreurs d'authentification qui révèlent des informations, des réponses de limitation de vitesse que vous ne gérez pas correctement, et des temps d'attente de passerelle qui pointent vers la mauvaise couche.
301 vs 302 vs 307 vs 308 : Le Matrice des Redirections
L'erreur que tout le monde commet au moins une fois : vous utilisez 301 Moved Permanently lors de tests d'une restructuration d'URL. Cela fonctionne. Vous passez à autre chose. Puis vous restructuriez à nouveau. Et maintenant, une partie de vos utilisateurs — ceux qui ont visité avant la deuxième modification — sont envoyés vers l'ancienne destination, stockée de façon permanente dans leur navigateur.
Le 301 est permanent et il cache de façon agressive. Les navigateurs définissent le TTL de la redirection en cache à l'infini, sauf si vous avez défini un Cache-Control en-tête. Il n'existe pas de méthode programmable pour expirer ce cache dans le navigateur de l'utilisateur. Si vous êtes encore en train de définir votre structure d'URL, utilisez le 302.
Le problème de conservation de la méthode est une autre chose. Lorsqu'un navigateur suit une redirection 301 ou 302, il peut (et en pratique, presque toujours) réduire une requête POST en une requête GET lors de la redirection. Cela constitue une violation technique du spécifié HTTP/1.0, mais les navigateurs l'ont normalisé depuis longtemps, de sorte que l'RFC 7231 l'acknowledge comme comportement standard. Si vous redirigez une requête POST — par exemple, après une soumission de formulaire — et que vous attendez la conservation de la méthode, vous devez utiliser le 307 ou le 308.
| Code | Permanent ? | Conserve-t-il la méthode ? | Utilisez-le pour |
|---|---|---|---|
| 301 | Oui | Non (POST → GET) | Redirection permanente où une requête GET est acceptable après redirection |
| 302 | Non | Non (POST → GET) | Redirections temporaires, flags de fonctionnalité, tests A/B |
| 307 | Non | Oui | Redirections temporaires où la méthode doit être conservée |
| 308 | Oui | Oui | Redirections permanentes où la méthode doit être conservée |
Le support du 308 est solide aujourd'hui — Chrome, Firefox, Safari et Edge le gèrent correctement. La réserve : certains clients API et bibliothèques HTTP plus anciens ne le suivent pas correctement, donc si vous redirigez des communications entre machines et que vous ne contrôlez ni le client ni sa bibliothèque HTTP, testez-le explicitement.
401 vs 403 : Authentification vs Autorisation
Le 401 signifie « vous n'êtes pas identifié ». Le spécifié exige qu'il inclue une WWW-Authenticate en-tête indiquant à l'application comment s'authentifier. C'est le bon code lorsque la session n'est pas valide, qu'aucun token n'est présent ou que le token a expiré.
Le 403 signifie « je sais qui vous êtes et la réponse est non ». L'utilisateur est authentifié mais manque des permissions. Retourner un 403 sur un token expiré est faux — c'est un 401. Retourner un 401 sur une demande avec des permissions valides mais insuffisantes est aussi faux, et pire encore, cela confond votre débogage d'authentification : vous chercherez des crédentielles manquantes alors que le problème réel est l'attribution des rôles.
L'argument de sécurité pour retourner 404 au lieu de 403 est réel. Si votre API retourne un 403 sur GET /admin/users, vous avez simplement indiqué à tout attaquant que l'endpoint existe et qu'ils auraient besoin de privilèges supérieurs pour l'atteindre. Retourner un 404 au lieu de 403 ne révèle aucune information sur l'existence de la ressource. C'est une décision : le 403 est techniquement correct et plus facile à déboguer ; le 404 est la meilleure option pour des endpoints sensibles où l'enumerabilité est importante.
429 : La limitation de vitesse est inutile sans Retry-After
Une réponse 429 sans un Retry-After en-tête est un boîte noire. Le client sait qu'il a été limité. Il ne sait pas s'il doit attendre 100 ms ou 24 heures. La plupart des implémentations de clients retentissent immédiatement (en surchargeant votre limite de vitesse) ou abandonnent complètement.
Retry-After prend soit une valeur entière (en secondes à attendre) soit une date HTTP (lorsqu'il faut réessayer) :
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1749254400
Le X-RateLimit-* les en-têtes ne sont pas dans aucune RFC — elles sont une norme de facto provenant de l'API de GitHub que tout le monde a copiée. Incluez-les en parallèle avec Retry-After. Le trio de Limit/Remaining/Reset indique au client où il en est avant d'atteindre la limite, ce qui est plus utile que simplement de savoir qu'il a atteint la limite.
Une chose à souligner : Retry-After est également valide sur les réponses 503, et cela signifie la même chose — « revenez dans ce nombre de secondes ». Si votre service est temporairement indisponible pour une fenêtre de maintenance, envoyez un 503 avec Retry-After au lieu de simplement couper les connexions.
503 vs 504 : Où se situe l'erreur ?
Ces deux codes semblent similaires mais pointent vers des couches complètement différentes de défaillance, et les confondre vous mène dans la mauvaise direction pour le débogage.
503 Service Unavailable Signifie que le serveur que vous avez atteint ne peut pas gérer la requête en ce moment — il est surchargé, en mode maintenance ou une dépendance backend est en panne. Le serveur lui-même a répondu ; il refuse simplement le travail.
504 Gateway Timeout Signifie qu'un proxy ou une passerelle (votre équilibreur de charge, nginx, passerelle API, CDN) a tenté d'atteindre un serveur supérieur et n'a pas reçu de réponse dans le délai prévu. Le serveur que vous avez atteint est vivant. Le service derrière n'est pas en réponse.
En pratique : si vous êtes derrière nginx et que votre serveur d'application (Node, Rails, Django, etc.) tombe, vous obtenez un 502 Bad Gateway — nginx a reçu une réponse, mais elle était corrompue. Si le serveur d'application cesse complètement de répondre, vous obtenez un 504. Si vous retournez un erreur intentionnellement à la couche d'application, vous obtenez un 503. La distinction importe lors du triage : le 504 signifie que vous devez examiner le service supérieur, votre configuration de délai, et votre réseau. Le 503 signifie que vous devez examiner l'application elle-même.
422 vs 400 : Les erreurs de validation ont leur propre code
400 Bad Request est pour les requêtes que le serveur ne peut pas parser — JSON mal formé, syntaxe invalide dans la chaîne de requête, en-têtes requises manquantes. C'est un problème structurel.
422 Unprocessable Entity est pour les requêtes que le serveur comprend mais ne peut pas agir car les données échouent à la validation — une plage de dates où le début est après la fin, un champ email avec une adresse invalide, un champ de quantité négatif. La requête était syntaxiquement correcte. Les sémantiques étaient fausses.
La plupart des APIs fusionnent les deux en 400 et cachent les détails de validation dans le corps de la réponse. Cela fonctionne, mais cela rend la gestion des erreurs côté client plus difficile : les clients doivent parser le corps pour savoir s'il s'agit d'une erreur de parsing ou d'une erreur de validation. L'utilisation du 422 pour les erreurs de validation permet aux clients d'identifier le code d'état. Rails l'a fait correctement depuis toujours ; le JSON:API spec spécifie le 422 pour les erreurs de validation.
Une nuance : le 422 est défini dans WebDAV (RFC 4918), pas dans le spécifié HTTP principal. En pratique, cela n'a pas d'importance — tous les clients et serveurs HTTP le gèrent bien — mais vous rencontrerez parfois un rigueur qui insiste pour utiliser le 400 au lieu. Ils n'ont pas tout à fait tort. Mais le 422 est plus spécifique et largement compris.
204 vs 200 avec un corps vide : l'un est correct pour DELETE
Lorsqu'un DELETE réussit, la réponse correcte est 204 No Content — pas 200 avec un corps vide, ni 200 avec {"success": true}.
Le 204 est le signal explicite que « cela a réussi et il n'y a pas de corps de réponse intentionnel ». Un 200 avec un corps vide est techniquement valide, mais il est ambigu — les clients ne savent pas si le corps était censé être présent et est perdu, ou si l'absence est intentionnelle. Le 204 élimine cet ambigüité.
La même logique s'applique aux requêtes PUT et PATCH lorsque vous ne retournez pas l'objet mis à jour. Si votre API retourne l'objet mis à jour après un PATCH, utilisez le 200. Si elle ne le fait pas, utilisez le 204. Ne retournez pas un 200 avec un corps vide de {} ou null — c'est le 204 vêtu d'un costume.
Une particularité : le 204 ne doit pas inclure un corps de message selon l'RFC 9110. Si vous retournez un 204 et que vous incluez par erreur un corps (certains frameworks vous permettent cela), certains clients HTTP le gèrent correctement, d'autres non. Supprimez le corps dans votre gestionnaire de réponse, pas seulement dans votre intention.
Référence rapide : Les codes qui piquent et pourquoi
| Code | Signification | Erreur courante | Solution |
|---|---|---|---|
| 301 | Redirection permanente | Utilisation de pendant les tests — maintenant elle est stockée de façon permanente | Utilisez le 302 jusqu'à ce que la redirection soit confirmée permanente |
| 302 | Redirection temporaire | Une requête POST est réduite à GET lors de la redirection | Utilisez le 307 si la méthode doit être conservée |
| 307 | Redirection temporaire (sécurisée en méthode) | Confondue avec 302 | Utilisez le 307 lors de redirections temporaires de POST/PUT/PATCH |
| 308 | Redirection permanente (sécurisée en méthode) | Ignorée en faveur du 301 par habitude | Utilisez le 307 au lieu du 301 lorsque la méthode est importante |
| 400 | Demande invalide (erreur de parsing) | Utilisée pour les erreurs de validation | Utilisez le 422 pour les échecs de validation où le corps était parseable |
| 401 | Non authentifié | Retourné lorsque l'utilisateur manque de permissions (doit être 403) | Retournez uniquement le 401 lorsque les identifiants sont manquants ou expirés |
| 403 | Interdire | Retourné au lieu du 404 pour des endpoints sensibles | Considérez le 404 lorsque la cacheture de l'existence de l'endpoint est importante |
| 422 | Entité non traitable | Fusionnée dans le 400 | Utilisez le 422 pour les échecs de validation où le corps était parseable |
| 429 | Limite de vitesse atteinte | Absence de header Retry-After | Incluez toujours le header Retry-After + X-RateLimit-* |
| 503 | Service indisponible | Confondue avec le 504 | Utilisez le 503 lorsque le serveur atteint ne peut pas gérer la requête |
| 504 | Temps d'attente de passerelle | Confondue avec le 503 | Examinez le service supérieur, pas le passerelle |
| 204 | Aucun contenu | Retour d'un 200 avec un corps vide au lieu | Utilisez le 204 pour les suppressions réussies de DELETE/PUT/PATCH sans corps de réponse |
Si vous devez rapidement consulter un code d'état pendant le débogage, IO Tools dispose d'une recherche des codes d'état HTTP qui couvre l'ensemble de la gamme avec des descriptions et des notes sur l'utilisation de chaque code.
Le modèle derrière tous ces cas
La plupart de ces erreurs proviennent d'un même endroit : traiter les codes d'état comme des catégories floues (« les 4xx sont des erreurs du client, les 5xx sont des erreurs du serveur, c'est tout ») plutôt que comme un protocole avec des sémantiques précises. Les sémantiques importent car les clients — navigateurs, bibliothèques HTTP, CDNs, outils de surveillance — s'appuient sur elles. Un CDN ne cache pas de la même manière un 200 et un 204. Un client HTTP ne réessaye pas un 400 et un 503 avec la même logique. Un navigateur ne cache pas un 302 et un 301 avec le même TTL.
Utilisez le bon code. L'overhead est nul. Le bénéfice de débogage lorsque quelque chose casse est non négligeable.
Installez nos extensions
Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide
恵 Le Tableau de Bord Est Arrivé !
Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !
Outils essentiels
Tout voir Nouveautés
Tout voirMise à jour: Notre dernier outil was added on Juin 26, 2026
