Menu

Express Router et routing : routes, paramètres, préfixes

Une route Express, c'est une méthode, un chemin et un handler : app.get('/users/:id', handler). Regroupez les routes liées dans un express.Router() et montez-le sous un préfixe avec app.use('/api', router).

Cette page contient des éditeurs exécutables. Modifiez, exécutez et voyez la sortie instantanément.

Le routing dans Express associe une méthode HTTP et un chemin à une fonction handler : app.get('/users', handler) répond aux requêtes GET sur /users, et app.post(), app.put() et app.delete() font de même pour les autres méthodes. Un segment qui commence par deux-points, comme dans /users/:id, est un paramètre de route dont la valeur arrive dans req.params. Pour garder une application qui grandit en ordre, placez les routes liées dans un express.Router() et montez-le sous un préfixe avec app.use('/api', router).

GET /users/2 répond {"id":2,"name":"Linus"}. Les paramètres de route sont toujours des chaînes, c'est pourquoi le handler compare avec Number(req.params.id). Envoyez POST /users avec le corps {"name": "Grace"} pour obtenir 201, puis DELETE /users/1 et GET /users pour voir la liste changer.

express.Router() avec un préfixe

Un router est une mini-application avec ses propres routes et middlewares. Ses chemins sont relatifs : une route écrite /:id dans un router monté sur /api/books répond à /api/books/:id. Dans un vrai projet, chaque router vit dans son propre fichier et se termine par module.exports = router.

GET /api/books/1 renvoie {"id":1,"title":"Dune"}. router.route('/:id') écrit le chemin une seule fois et enchaîne un handler par méthode ; envoyez PUT /api/books/1 et vous obtenez {"updated":"1"}. Remplacez le chemin de montage par /v2/books et le même router y répond à la place.

L'ordre des routes : la première qui correspond gagne

Express essaie les routes dans l'ordre d'enregistrement et s'arrête à la première qui envoie une réponse. Une route à paramètre attrape tout ce qui se trouve à sa position, donc un chemin fixe enregistré après elle n'est jamais atteint :

GET /users/new répond {"route":"/users/:id","id":"new"} : la route à paramètre a été enregistrée en premier et l'a prise. Déplacez la route /users/new au-dessus de /users/:id et relancez pour obtenir {"route":"/users/new"}. Envoyez ensuite GET /books pour atteindre le handler 404 tout en bas.

Le handler 404

Express répond à une requête sans route correspondante avec sa propre page HTML, Cannot GET /books. Pour une API, on veut en général du JSON, donc ajoutez un app.use() sans chemin comme toute dernière route, comme dans le bloc ci-dessus. Il ne s'exécute que si toutes les routes précédentes ont laissé passer la requête. Les erreurs levées par les handlers sont un autre cas, avec leur propre handler à quatre arguments, présenté dans la gestion des erreurs Express.

Les chemins de route dans Express 5

Express 5 a changé la syntaxe des chemins, et la plupart des extraits de code en ligne sont écrits pour Express 4 :

MotifExpress 4Express 5
N'importe quel cheminapp.get('*', fn)app.get('/*splat', fn)
Paramètre optionnel/users/:id?/users{/:id}
Motif sur un paramètre/users/:id(\\d+)Non pris en charge ; vérifiez la valeur dans le handler

Un * seul ou un ? après un paramètre lève une TypeError à l'enregistrement de la route, donc l'application ne démarre pas.

Erreurs fréquentes

Enregistrer le handler 404 en premier. app.use() sans chemin correspond à tout, donc toutes les requêtes reçoivent le 404. Gardez-le tout en bas.

Oublier que le préfixe est retiré. Dans un router monté sur /api, req.path n'inclut pas /api. Utilisez req.originalUrl quand vous avez besoin du chemin complet.

Comparer un paramètre avec un nombre. req.params.id === 1 est toujours faux, car req.params.id est la chaîne '1'.

Questions fréquentes

Quelle différence entre app.use et app.get ?

app.get('/users', fn) n'exécute fn que pour les requêtes GET dont le chemin est exactement /users. app.use('/users', fn) s'exécute pour toutes les méthodes et pour tout chemin qui commence par /users, c'est pourquoi on l'utilise pour monter des routers et des middlewares.

Comment rendre les routes Express sensibles à la casse ?

Par défaut, les routes ignorent la casse, donc /Users correspond à /users. Désactivez ce comportement avec app.set('case sensitive routing', true), ou par router avec express.Router({ caseSensitive: true }).

Pourquoi req.params est-il vide dans un router imbriqué ?

Un router ne voit que les paramètres de ses propres chemins. S'il est monté sur /users/:userId/posts, créez-le avec express.Router({ mergeParams: true }) pour que req.params.userId du chemin parent soit disponible.

Faut-il mettre toutes les routes dans un seul fichier ?

Pas au-delà de quelques routes. Créez un router par ressource (routes/users.js, routes/orders.js), exportez-le avec module.exports = router et montez chacun dans le fichier principal avec app.use().

Illustration des langages de programmation de Coddy

Apprendre à coder avec Coddy

Commencer