Accueil / Articles / Identifier ou façonner : choisir les paramètres de route ou les chaînes de requête dans Express

Identifier ou façonner : choisir les paramètres de route ou les chaînes de requête dans Express

Apprenez quand une valeur doit figurer dans un paramètre de route Express plutôt que dans une chaîne de requête, comment lire req.params et req.query, ainsi que comment gérer les valeurs par défaut et les types de manière sécurisée.

1324 mots

Prenons l’URL /users/42?sort=name&order=asc. Le 42 désigne un utilisateur en particulier ; sort=name&order=asc ne fait que modifier l’ordre d’affichage des résultats. Mélanger ces deux rôles, par exemple en utilisant un ID comme filtre ou inversement, est une cause fréquente de problèmes avec les routes Express. Après avoir lu ce guide, vous disposerez d’un test simple pour déterminer à quel endroit une valeur doit être placée, et vous saurez comment Express gère chaque type de paramètre ainsi quels problèmes il peut engendrer.

Les paramètres de route identifient une ressource

/users/:id

Le deux-points indique que :id est un espace réservé. Lorsqu’une requête pour /users/42 arrive, Express correspond au motif et enregistre 42 comme valeur de id. La même logique s’applique à tout élément disposant d’une identité :

/users/42        → which user
/products/17      → which product
/orders/1042      → which order

Chacun de ces chemins désigne précisément une seule chose. Sans ce segment, la question « lequel ? » n’a pas de réponse.

Les chaînes de requête façonnent la réponse

Une chaîne de requête correspond à tout ce qui se trouve après le ? : une liste de paires clé=valeur reliées par &. Elle ne sélectionne pas d’élément, mais filtre, trie, pagine ou modifie d’une autre manière ce qui est retourné.

/users?sort=name&order=asc

Ici, sort et order laissent l’élément (la collection des utilisateurs) inchangé et n’affectent que sa présentation. Exemples plus courants :

/products?category=electronics&maxPrice=500
/search?q=laptop&page=2

Un test à une question pour les distinguer

Demandez ce qui se passe si vous supprimez la valeur :

  • Si le chemin n’a plus de sens (on ne peut pas récupérer « un utilisateur » sans préciser lequel), la valeur est un identifiant et doit figurer dans le chemin.
  • Si le chemin continue de fonctionner et renvoie simplement le résultat par défaut, non filtré (tous les utilisateurs, dans l’ordre standard), la valeur est un modificateur et doit figurer dans la chaîne de requête.

Ce test donne également des indications sur la gestion des erreurs. Une ressource manquante derrière un paramètre de chemin mérite généralement un code 404, tandis qu’un filtre qui ne correspond à rien devrait normalement renvoyer un code 200 avec une liste vide. Pour en savoir plus sur la conception de URL axée sur les ressources, consultez REST APIs pour débutants.

Lecture des paramètres de chemin avec req.params

Les paramètres sont déclarés avec un deux-points dans le chemin de la route, et leurs valeurs capturées apparaissent sous req.params avec les mêmes noms :

app.get("/users/:id", (req, res) => {
  const userId = req.params.id;
  res.send(`Fetching user with ID: ${userId}`);
});

Une requête vers /users/42 définit req.params.id à la chaîne de caractères "42".

Plusieurs paramètres dans un même chemin

Les ressources imbriquées se contentent de déclarer davantage de placeholders :

app.get("/users/:userId/orders/:orderId", (req, res) => {
  const { userId, orderId } = req.params;
  res.send(`User ${userId}, Order ${orderId}`);
});

Pour /users/42/orders/1042, le déstructuring donne userId égal à "42" et orderId égal à "1042". Les noms des paramètres doivent être uniques au sein d’une route et décrire ce qu’ils identifient ; userId et orderId sont bien plus lisible que deux paramètres anonymes id.

Lecture des chaînes de requête avec req.query

Les valeurs de requête n’ont pas besoin d’être déclarées dans la route. Express analyse tout ce qui suit le ? et le place dans req.query:

app.get("/users", (req, res) => {
  const { sort, order } = req.query;
  res.send(`Sorting by ${sort}, order: ${order}`);
});

Pour /users?sort=name&order=asc, on obtient req.query.sort avec la valeur "name" et req.query.order avec la valeur "asc". La route reste /users, de sorte que le même gestionnaire s’occupe à la fois des requêtes simples et de celles triées.

Fournir des valeurs par défaut pour les champs optionnels

Puisque les clients omettent souvent des valeurs de requête, les gestionnaires recourent généralement à des valeurs par défaut raisonnables :

app.get("/products", (req, res) => {
  const sort = req.query.sort || "default";
  const page = req.query.page || 1;
  res.send(`Sorting: ${sort}, Page: ${page}`);
});

Une requête simple vers /products fonctionne néanmoins, en utilisant les valeurs par défaut. Faites attention à un détail : lorsque le client envoie bien page=2, page est la chaîne "2", mais lorsqu’il est omis, c’est le nombre 1. De tels types mixtes provoquent des erreurs ultérieurement (concaténation de chaînes au lieu d’addition, par exemple). Convertissez explicitement, comme avec Number(req.query.page) || 1, et validez le résultat avant de l’utiliser dans une requête de base de données.

Les valeurs ne sont pas toujours des chaînes simples

Un paramètre répété dans l’URL, comme ?tag=a&tag=b, est traité comme un tableau plutôt que comme une chaîne. Selon les paramètres du parseur de requête, la syntaxe entre crochets peut également générer des objets imbriqués. Express 5 a remplacé le parseur par défaut par un modèle plus simple que celui utilisé par Express 4 ; vérifiez donc la documentation de votre version si vous comptez sur des objets de requête imbriqués. Quoi qu’il en soit, ne supposez jamais le type d’une valeur de requête ; considérez toujours req.query comme une entrée non fiable.

Déterminer quel type de paramètre une route nécessite

Paramètres de chemin pour une ressource spécifique

app.get("/users/:id", ...)          // one specific user
app.get("/products/:id", ...)       // one specific product
app.get("/orders/:orderId", ...)    // one specific order

Chacune de ces routes fait référence à un élément unique et précis. Si la route n’a de sens que grâce à une valeur, placez cette valeur dans le chemin.

Chaînes de requête pour le filtrage, le tri et la pagination

app.get("/users", ...)     // ?role=admin&status=active
app.get("/products", ...)  // ?category=electronics&maxPrice=500&sort=price
app.get("/search", ...)    // ?q=laptop&page=2

Chacun d’eux reste compréhensible sans aucune requête : « tous les utilisateurs », « tous les produits » ou une page de recherche vide. Les valeurs qui ne font que restreindre ou réordonner les résultats sont des modificateurs optionnels et doivent être placés après le ?.

Combinaison des deux dans une même route

Les points d’entrée réels utilisent fréquemment les deux en même temps. Le paramètre sélectionne le propriétaire, tandis que la requête restreint les données associées :

app.get("/users/:id/orders", (req, res) => {
  const userId = req.params.id;         // which user
  const status = req.query.status;      // optional filter: only their pending orders, for example

  res.send(`Orders for user ${userId}, filtered by status: ${status || "all"}`);
});

Une requête vers /users/42/orders?status=pending se lit naturellement : 42 indique à quels utilisateurs appartiennent les commandes, et status=pending précise quelles de ces commandes inclure. Lorsque status est absent, le gestionnaire renvoie « tous », ce qui correspond à l’idée qu’un modificateur manquant signifie un résultat non filtré.

Questions fréquentes

Une seule route peut-elle utiliser les deux ?

Oui, et c’est très courant. L’exemple combiné ci-dessus représente le schéma typique : un identifiant pour la ressource parente ainsi que des filtres optionnels pour ses enfants.

Les paramètres sont-ils toujours obligatoires et les valeurs de requête toujours optionnelles ?

C’est une convention forte, mais pas une règle stricte. Express prend en charge des segments de chemin optionnels, et rien n’empêche une API d’exiger une valeur de requête. Néanmoins, la règle pratique reste valable : les identifiants obligatoires se trouvent dans le chemin, tandis que les modificateurs optionnels sont ajoutés à la requête avec des valeurs par défaut.

req.params.id est-il un nombre ?

Non. Tout ce qui est extrait d’une URL est une chaîne de caractères, même s’il semble numérique. Convertissez-le explicitement, par exemple avec Number(req.params.id), et rejetez les valeurs qui donnent NaN avant d’accéder à la base de données.

Que se passe-t-il si une valeur de requête attendue manque ?

La clé fait simplement défaut dans req.query, ce qui entraîne une valeur undefined lors de sa lecture. C’est précisément pour cette raison que les valeurs par défaut présentées précédemment constituent une pratique standard.

En résumé

Les deux types de valeurs se trouvent dans la même URL, mais elles remplissent des fonctions différentes. Les paramètres de route, lus depuis req.params, désignent l’élément spécifique auquel concerne la requête. Les chaînes de recherche, lues depuis req.query, permettent de filtrer, trier ou paginer les résultats, et doivent disposer de valeurs par défaut. Traitez-les toutes deux comme des chaînes non typées provenant de l’extérieur : convertissez-les et validez-les avant utilisation, afin que la conception de vos routes reste prévisible à mesure que l’API évolue.

Lectures complémentaires

  • Du chargement à l’URL : stockage et service sécurisés des fichiers utilisateurs dans Express — Découvrez où les applications Express doivent conserver les fichiers téléchargés, comment express.static associe un dossier à des URLs, et quels mécanismes de protection empêchent que les téléchargements des utilisateurs ne deviennent une faille de sécurité.