324 votes

Passer des variables au middleware suivant en utilisant next() dans Express.js

Je veux passer une variable du premier middleware à un autre middleware, et j'ai essayé de le faire, mais il y avait "req.somevariable est donné comme 'undefined'".


//app.js
..
app.get('/someurl/', middleware1, middleware2)
...

////middleware1
...
quelques conditions
...
res.somevariable = variable1;
next();
...

////middleware2
...
quelques conditions
...
variable = req.somevariable;
...

687voto

Cole Chamberlain Points 1263

API v4.x docs

C'est à quoi sert l'objet res.locals. Il n'est pas pris en charge ou documenté de définir des variables directement sur l'objet de la requête. res.locals est garanti de conserver l'état pendant toute la durée d'une requête.

Citation de la documentation :

Un objet contenant des variables locales de réponse limitées à la requête, et donc disponibles uniquement pour la ou les vues rendues pendant ce cycle de requête / réponse (s'il y en a). Autrement, cette propriété est identique à app.locals.

Cette propriété est utile pour exposer des informations au niveau de la requête telles que le nom du chemin de la requête, l'utilisateur authentifié, les paramètres de l'utilisateur, etc.

app.use(function(req, res, next) {
    res.locals.user = req.user;  
    res.locals.authenticated = !req.user.anonymous;
    next();
});

Pour récupérer la variable dans le middleware suivant :

app.use(function(req, res, next) {
    if (res.locals.authenticated) {
        console.log(res.locals.user.id);
    }
    next();
});

288voto

Amberlamps Points 5120

Attachez votre variable à l'objet res.locals, pas à req.

Au lieu de

req.somevariable = variable1;

Avoir:

res.locals.somevariable = variable1;

Comme d'autres l'ont souligné, res.locals est la manière recommandée de passer des données à travers le middleware.

45voto

Doron Segal Points 205

Je ne pense pas que la meilleure pratique soit de passer une variable comme req.YOUR_VAR. Vous voudrez peut-être considérer req.YOUR_APP_NAME.YOUR_VAR ou req.mw_params.YOUR_VAR.

Cela vous aidera à éviter d'écraser d'autres attributs.

42voto

Niels Abildgaard Points 385

Le motif le plus courant pour transmettre des variables à d'autres middleware et fonctions de point de terminaison consiste à attacher des valeurs à l'objet de requête req.

Dans votre cas, cela signifierait d'avoir des middlewares comme ceux-ci:

app.use(function (req, res, next) {
  req.someVariable = 123;
  next();
});

app.use(function (req, res, next) {
  console.log("La variable est", req.someVariable);
  next();
});

Il existe de nombreux cas d'utilisation courants de ce modèle, et c'est la manière standard de le faire dans la communauté express. Voir, par exemple:


Il convient de noter que la réponse la plus fortement votée actuellement recommande incorrectement d'utiliser res.locals à cette fin---ce qui semble découler d'une mauvaise compréhension de la documentation. Pour cette raison, je vais expliquer pourquoi ce n'est pas l'approche habituelle du problème (bien que ce ne soit pas particulièrement préjudiciable non plus).

La documentation

Comme preuve à l'appui de l'approche res.locals étant la bonne pour le cas, la documentation maintenant obsolète est citée:

Un objet qui contient des variables locales de réponse spécifiques à la requête, et donc uniquement disponibles pour la vue(s) rendue pendant ce cycle de demande/réponse (le cas échéant). Sinon, cette propriété est identique à app.locals.

Cette propriété est utile pour exposer des informations au niveau de la demande telles que le nom du chemin de la demande, l'utilisateur authentifié, les paramètres de l'utilisateur, etc.

Remarquez le cadre ici: res.locals est destiné aux variables uniquement disponibles "pour la vue(s) rendue pendant cette demande" (emphasis ajouté).

C'est ce à quoi res.locals se rapporte. res.render rend un fichier de modèle avec des données données ainsi que l'accès aux variables locales. C'était en fait plus clair dans la [documentation v2](http://expressjs.com/2x/guide.html#res.local()), et nous avons maintenant mis à jour la documentation actuelle d'Express pour plus de clarté:

Utilisez cette propriété pour définir des variables accessibles dans les modèles rendus avec res.render. Les variables définies sur res.locals sont disponibles dans un seul cycle de demande-réponse, et ne seront pas partagées entre les demandes.

Pour conserver des variables locales pour une utilisation dans le rendu de modèles entre les demandes, utilisez plutôt app.locals.

Cette propriété est utile pour exposer des informations au niveau de la demande telles que le nom du chemin de la demande, l'utilisateur authentifié, les paramètres de l'utilisateur, etc. aux modèles rendus dans l'application.

(Emphasis ajouté.)

Le guide

D'autres preuves de l'extension de req étant l'approche standard se trouvent dans le guide sur Écriture de middleware, qui indique:

Ensuite, nous allons créer une fonction middleware appelée "requestTime" et ajouter une propriété appelée requestTime à l'objet de demande.

const requestTime = function (req, res, next) {
 req.requestTime = Date.now()
 next()
}

Lorsque cela a été mentionné dans la discussion dans les réponses à cette question, un utilisateur a répondu: "C'était la manière de le faire avant qu'ils ajoutent res.locals, donc les docs peuvent être anciennes. res.locals est un espace de noms spécifiquement pour cela."

Cela ne correspond cependant pas à l'historique de la base de code: les variables locales sont [présentes depuis v2](http://expressjs.com/2x/guide.html#res.locals()), ce qui est significativement avant par exemple l'inclusion de express.json dans la bibliothèque, moment à partir duquel il aurait été logique de changer le comportement, s'il était en effet correct de sauvegarder des valeurs dans res.locals.

Notes de clôture

Mention spéciale à @real_ate qui a écrit dans les commentaires, mais a été négligé.

8voto

SLaks Points 391154

C'est parce que req et res sont deux objets différents.

Vous devez rechercher la propriété sur le même objet auquel vous l'avez ajoutée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X