Les pubs vous déplaisent ? Aller Sans pub Auj.

Codes HTTP qui vous piquent vraiment — 301 vs 302, 401 vs 403, et le champ de 5xx

Publié le

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.

Les codes d'état HTTP qui vous piquent vraiment — 301 versus 302, 401 versus 403, et le champ de bataille des codes 5xx 1
ANNONCE · Supprimer ?

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.

CodePermanent ?Conserve-t-il la méthode ?Utilisez-le pour
301OuiNon (POST → GET)Redirection permanente où une requête GET est acceptable après redirection
302NonNon (POST → GET)Redirections temporaires, flags de fonctionnalité, tests A/B
307NonOuiRedirections temporaires où la méthode doit être conservée
308OuiOuiRedirections 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

CodeSignificationErreur couranteSolution
301Redirection permanenteUtilisation de pendant les tests — maintenant elle est stockée de façon permanenteUtilisez le 302 jusqu'à ce que la redirection soit confirmée permanente
302Redirection temporaireUne requête POST est réduite à GET lors de la redirectionUtilisez le 307 si la méthode doit être conservée
307Redirection temporaire (sécurisée en méthode)Confondue avec 302Utilisez le 307 lors de redirections temporaires de POST/PUT/PATCH
308Redirection permanente (sécurisée en méthode)Ignorée en faveur du 301 par habitudeUtilisez le 307 au lieu du 301 lorsque la méthode est importante
400Demande invalide (erreur de parsing)Utilisée pour les erreurs de validationUtilisez le 422 pour les échecs de validation où le corps était parseable
401Non authentifiéRetourné lorsque l'utilisateur manque de permissions (doit être 403)Retournez uniquement le 401 lorsque les identifiants sont manquants ou expirés
403InterdireRetourné au lieu du 404 pour des endpoints sensiblesConsidérez le 404 lorsque la cacheture de l'existence de l'endpoint est importante
422Entité non traitableFusionnée dans le 400Utilisez le 422 pour les échecs de validation où le corps était parseable
429Limite de vitesse atteinteAbsence de header Retry-AfterIncluez toujours le header Retry-After + X-RateLimit-*
503Service indisponibleConfondue avec le 504Utilisez le 503 lorsque le serveur atteint ne peut pas gérer la requête
504Temps d'attente de passerelleConfondue avec le 503Examinez le service supérieur, pas le passerelle
204Aucun contenuRetour d'un 200 avec un corps vide au lieuUtilisez 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.

Envie d'une expérience sans pub ? Passez à la version sans pub

Installez nos extensions

Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide

Sur Extension Chrome Sur Extension de bord Sur Extension Firefox Sur Extension de l'opéra

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 !

ANNONCE · Supprimer ?
ANNONCE · Supprimer ?
ANNONCE · Supprimer ?

Coin des nouvelles avec points forts techniques

Impliquez-vous

Aidez-nous à continuer à fournir des outils gratuits et précieux

Offre-moi un café
ANNONCE · Supprimer ?