04 - Les codes de statut HTTP qu'il faut connaître
Ce que tu vas apprendre
- Les codes de statut HTTP essentiels par famille (2xx, 3xx, 4xx, 5xx)
- Quel code utiliser dans chaque situation concrète
- Pourquoi renvoyer 200 pour tout est un anti-pattern destructeur
- Comment implementer les bons codes dans Express
Prerequisites
- Avoir lu l'article sur les méthodes HTTP
- Savoir ce qu'est une réponse HTTP
Le projet ou tout etait 200
J'ai hérité d'une API ou chaque endpoint renvoyait 200. Succes ? 200 avec {"success": true}. Erreur de validation ? 200 avec {"success": false, "error": "Invalid email"}. Ressource introuvable ? 200 avec {"success": false, "error": "Not found"}. Erreur serveur ? 200 avec... tu devines.
Le monitoring voyait 100% de succes. Le CDN cachait les erreurs. Les tests e2e ne detectaient rien. Et moi je perdais mes cheveux.
Les codes de statut HTTP existent depuis 1990. Ils sont compris par chaque navigateur, proxy, load balancer, outil de monitoring et CDN de la planete. Les ignorer, c'est se battre contre toute l'infrastructure du web.
Famille 2xx -- Succes
200 OK
La réponse standard pour un succes. Utilise-la pour GET et PATCH/PUT qui renvoient des donnees.
httpGET /api/users/42 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 42, "name": "Alice"}
201 Created
Une ressource a ete créée. Toujours avec un POST (et parfois PUT). Inclus le header Location.
httpPOST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Bob", "email": "bob@example.com"}
HTTP/1.1 201 Created
Location: /api/users/43
{"id": 43, "name": "Bob", "email": "bob@example.com"}
204 No Content
Succes, mais pas de body dans la réponse. Parfait pour DELETE et pour les mises à jour qui ne renvoient rien.
httpDELETE /api/users/42 HTTP/1.1
HTTP/1.1 204 No Content
En TypeScript :
typescriptrouter.delete("/api/users/:id", async (req, res) => {
await userService.delete(req.params.id);
res.status(204).end();
});
Famille 3xx -- Redirections
301 Moved Permanently
La ressource a définitivement change d'adresse. Les clients et moteurs de recherche doivent mettre à jour leurs liens.
304 Not Modified
Le client a une version cachee et elle est encore valide. Pas de body renvoye. Ca fonctionne avec les headers If-None-Match (ETag) ou If-Modified-Since.
httpGET /api/users/42 HTTP/1.1
If-None-Match: "abc123"
HTTP/1.1 304 Not Modified
Famille 4xx -- Erreur client
C'est la famille la plus riche et la plus mal utilisee.
400 Bad Request
La requête est malformee. JSON invalide, champ manquant, type incorrect.
typescriptrouter.post("/api/users", async (req, res) => {
const result = userSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: "Validation failed",
details: result.error.issues,
});
}
const user = await userService.create(result.data);
res.status(201).json(user);
});
401 Unauthorized
Le client n'est pas authentifié. Pas de token, token expire, token invalide. Le nom est trompeur -- ca devrait s'appeler "Unauthenticated".
403 Forbidden
Le client est authentifié mais n'a pas les droits. Il sait qui il est, mais il n'a pas acces.
typescriptrouter.delete("/api/users/:id", async (req, res) => {
if (req.user.role !== "admin") {
return res.status(403).json({
error: "Insufficient permissions",
});
}
// ...
});
404 Not Found
La ressource n'existe pas. Simple, efficace, universel.
409 Conflict
La requête entre en conflit avec l'état actuel. Utile pour les emails dupliques, les conflits de version, les états incoherents.
typescriptrouter.post("/api/users", async (req, res) => {
const existing = await userService.findByEmail(req.body.email);
if (existing) {
return res.status(409).json({
error: "Email already registered",
});
}
// ...
});
422 Unprocessable Entity
La requête est syntaxiquement valide mais semantiquement incorrecte. Le JSON est bien forme, mais les donnees n'ont pas de sens (date de fin avant la date de début, quantité negative...).
La frontiere avec 400 est floue. Mon approche : 400 pour les problèmes de format, 422 pour les problèmes de logique métier.
429 Too Many Requests
Rate limiting. Le client envoie trop de requêtes. Inclus le header Retry-After.
httpHTTP/1.1 429 Too Many Requests
Retry-After: 60
{"error": "Rate limit exceeded", "retryAfter": 60}
Famille 5xx -- Erreur serveur
500 Internal Server Error
Quelque chose a plante cote serveur. Le client n'y peut rien.
502 Bad Gateway
Le serveur agit comme proxy et a reçu une réponse invalide du serveur en amont. Courant avec les reverse proxies.
503 Service Unavailable
Le serveur est temporairement indisponible (maintenance, surcharge). Inclus Retry-After.
L'anti-pattern 200-pour-tout
Pourquoi c'est si grave ?
typescript// Anti-pattern : 200 pour tout
router.get("/api/users/:id", async (req, res) => {
try {
const user = await userService.findById(req.params.id);
if (!user) {
return res.json({ success: false, error: "Not found" }); // 200!
}
res.json({ success: true, data: user }); // 200!
} catch (err) {
res.json({ success: false, error: "Server error" }); // 200!
}
});
// Correct : codes semantiques
router.get("/api/users/:id", async (req, res) => {
try {
const user = await userService.findById(req.params.id);
if (!user) {
return res.status(404).json({ error: "User not found" });
}
res.json(user);
} catch (err) {
res.status(500).json({ error: "Internal server error" });
}
});
Avec les bons codes, ton monitoring sait que 4% de tes requêtes sont des 404, que les 500 ont spike a 3h du matin, que le rate limiting a bloque 200 requêtes. Avec 200 partout, tu es aveugle.
Retrouve un aide-mémoire complet des codes HTTP sur paltemps.fr.
Résumé
- Utilise les codes de statut HTTP -- ils sont compris par toute l'infrastructure web
- 201 pour les creations, 204 pour les suppressions, pas 200 pour tout
- 400 pour les problèmes de format, 422 pour la logique métier, 409 pour les conflits
- 401 = pas authentifié, 403 = pas autorise
- L'anti-pattern 200-pour-tout rend ton monitoring inutile
Precedent : Les méthodes HTTP | Suivant : Body et headers
Sources
- MDN Web Docs -- HTTP response status codes. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
- RFC 9110 -- HTTP Semantics, Section 15. https://www.rfc-editor.org/rfc/rfc9110#section-15
- HTTP Status Dogs (pour memoriser avec le sourire). https://httpstatusdogs.com/