Validez les données au bord de l'API et centralisez toute la gestion d'erreurs dans un middleware unique à quatre paramètres.
Ouvrir cette leçon dans KodokonToute donnée entrante est hostile jusqu'à preuve du contraire : corps JSON, paramètres d'URL, en-têtes. La validation appartient au bord de l'application - avant le contrôleur - pour que les couches internes travaillent sur des données garanties. Distinguez ensuite deux familles d'erreurs : les erreurs opérationnelles (entrée invalide, ressource absente, conflit), attendues et traduites en 4xx, et les erreurs de programmation (bugs), qui doivent produire un 500 opaque côté client et une trace complète côté serveur.
export class HttpError extends Error {
constructor(status, message, details = undefined) {
super(message);
this.status = status;
this.details = details;
}
}Un middleware de validation intercepte la requête avant le contrôleur. La version manuelle ci-dessous montre le principe ; en production, un schéma déclaratif (zod s'est imposé comme standard) apporte en plus l'inférence de types et des messages structurés. Le compromis : une dépendance et un léger coût à l'exécution, contre des règles centralisées, composables et impossibles à oublier.
import { HttpError } from './http-error.js';
export function validateUser(req, res, next) {
const { email, name } = req.body ?? {};
const errors = [];
if (typeof email !== 'string' || !email.includes('@')) {
errors.push('email: invalid format');
}
if (typeof name !== 'string' || name.trim().length < 2) {
errors.push('name: 2 characters minimum');
}
if (errors.length > 0) {
return next(new HttpError(400, 'Invalid body', errors));
}
next();
}Express reconnaît un middleware d'erreur à sa signature à quatre paramètres (err, req, res, next). Enregistré en dernier, après toutes les routes avec app.use(errorHandler), il devient l'unique sortie d'erreur de l'API : format de réponse homogène, journalisation en un seul point, aucune fuite d'information interne. Les contrôleurs, eux, se contentent d'appeler next(err).
export function errorHandler(err, req, res, next) {
if (res.headersSent) {
return next(err);
}
const status = err.status ?? 500;
const body = { error: err.message };
if (err.details) {
body.details = err.details;
}
if (status >= 500) {
console.error(err);
body.error = 'Internal server error';
}
res.status(status).json(body);
}