Introduction
Chaque API reçoit des données qu'elle n'a pas créées. Les utilisateurs envoient du JSON mal formé, des champs manquants, des chaînes de caractères là où il faudrait des nombres, et des payloads techniquement valides mais logiquement incorrects. Sans couche de validation, ces problèmes corrompent silencieusement votre base de données ou déclenchent des erreurs 500 cryptiques. Sans couche de gestion des erreurs cohérente, chaque route réagit différemment en cas de problème — certaines renvoient de simples chaînes, d'autres des pages d'erreur HTML, d'autres encore ne renvoient rien du tout.
Cette leçon construit ces deux couches : la validation des requêtes à l'aide de la bibliothèque express-validator, et un gestionnaire d'erreurs centralisé qui donne à chaque réponse d'erreur la même forme prévisible.
Validation des données de requête entrantes
express-validator encapsule la bibliothèque éprouvée validator.js et se branche directement en tant que middleware Express. Installez-la dans votre projet :
Les règles de validation sont définies comme un tableau de middlewares et attachées à une route avant l'exécution du handler. Voici une route POST /users qui exige un e-mail valide et un mot de passe d'au moins huit caractères :
L'appel à validationResult(req) collecte toutes les violations trouvées par la chaîne de règles. Si le tableau n'est pas vide, la requête est immédiatement rejetée avec le statut HTTP 422 Unprocessable Entity — le statut sémantiquement correct lorsque le serveur comprend la requête mais ne peut pas la traiter car les données sont invalides.
Vous pouvez extraire les règles de validation dans un fichier séparé à mesure que le nombre de routes augmente, afin de garder les fichiers de routes concentrés uniquement sur la logique métier.
Construction d'un gestionnaire d'erreurs centralisé
Express dispose d'une signature de middleware spéciale pour la gestion des erreurs : quatre paramètres au lieu de trois. Tout middleware ou route qui appelle next(err) ou qui lève une exception à l'intérieur d'un wrapper async ignore les middlewares classiques et atterrit ici.
Créez un fichier dédié :
Enregistrez-le après toutes vos routes dans le fichier principal de l'application. L'ordre est important — Express n'invoque ce handler que s'il est défini en dernier :
Désormais, n'importe quelle route peut signaler un problème en attachant un statusCode à un objet Error et en le passant à next :
Chaque erreur, attendue ou non, passe désormais par le même handler et renvoie la même forme JSON. Les équipes frontend peuvent écrire une seule fonction de parsing d'erreur au lieu de deviner ce que chaque endpoint renvoie.
Création d'une classe AppError personnalisée
Passer des objets Error bruts avec des propriétés statusCode attachées manuellement devient répétitif. Une petite classe personnalisée permet de clarifier cela :
Le flag isOperational permet à votre gestionnaire d'erreurs de se comporter différemment selon qu'il s'agit d'erreurs que vous avez délibérément lancées ou de plantages d'exécution inattendus :
Vous pouvez vérifier isOperational dans le gestionnaire d'erreurs pour décider s'il faut logger une stack trace complète, envoyer une alerte, ou simplement renvoyer le message tel quel.
Erreurs fréquentes
Placer le gestionnaire d'erreurs avant vos routes est l'erreur la plus courante — il ne se déclenche jamais parce qu'aucune erreur n'a encore été transmise. Enregistrez-le toujours en dernier.
Utiliser le HTTP 400 pour chaque erreur client est imprécis. Utilisez 400 pour une syntaxe mal formée, 401 quand l'authentification est manquante, 403 quand l'utilisateur est authentifié mais non autorisé, 404 quand une ressource n'existe pas, et 422 quand la structure est valide mais que le contenu échoue aux règles métier.
Exposer les stack traces en production est un vrai risque de sécurité. L'opérateur de décomposition conditionnel dans l'exemple d'errorHandler ci-dessus (process.env.NODE_ENV === 'development') garantit que les stacks n'apparaissent qu'en local.
Oublier d'envelopper les handlers de route async dans un try/catch signifie que les rejets de promesse non gérés contournent entièrement votre gestionnaire d'erreurs. Un petit utilitaire wrapper async permet d'imposer ce pattern dans toutes les routes sans ajouter de boilerplate.
Résumé
La validation avec express-validator bloque les mauvaises données à l'entrée et renvoie un retour structuré au client. Un gestionnaire d'erreurs centralisé avec une forme JSON cohérente rend votre API prévisible pour les consommateurs et plus facile à maintenir à mesure qu'elle grandit. La classe AppError fait le lien entre ces deux préoccupations — elle offre un moyen propre de signaler des échecs attendus depuis n'importe quel endroit de votre code, et laisse un seul handler décider de la réponse à apporter.
Point de contrôle de la leçon
Révisez la leçon et recevez des conseils sur votre travail.