Pasar variables al siguiente middleware usando next() en Express.js

Resuelto user2791897 asked hace 11 años • 9 respuestas

Quiero pasar alguna variable del primer middleware a otro middleware, e intenté hacer esto, pero había " req.somevariableun valor dado como 'indefinido'".


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

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

////middleware2
...
some conditions
...
variable = req.somevariable;
...
user2791897 avatar Sep 18 '13 21:09 user2791897
Aceptado

Documentos API v4.x

Para esto está el objeto res.locals . No se admite ni documenta la configuración de variables directamente en el objeto de solicitud. Se garantiza que res.locals mantendrá el estado durante la vida de una solicitud.

Cita de los documentos:

Un objeto que contiene variables locales de respuesta con alcance para la solicitud y, por lo tanto, disponible solo para las vistas representadas durante ese ciclo de solicitud/respuesta (si corresponde). De lo contrario, esta propiedad es idéntica a app.locals.

Esta propiedad es útil para exponer información a nivel de solicitud, como el nombre de la ruta de la solicitud, el usuario autenticado, la configuración del usuario, etc.

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

Para recuperar la variable en el siguiente middleware:

app.use(function(req, res, next) {
    if (res.locals.authenticated) {
        console.log(res.locals.user.id);
    }
    next();
});
cchamberlain avatar Jul 13 '2016 15:07 cchamberlain

Adjunte su variable al res.localsobjeto, no req.

En lugar de

req.somevariable = variable1;

Tener:

res.locals.somevariable = variable1;

Como otros han señalado, res.localses la forma recomendada de pasar datos a través de middleware.

Amberlamps avatar Sep 18 '2013 14:09 Amberlamps

No creo que la mejor práctica sea pasar una variable como req.YOUR_VAR. Quizás quieras considerar req.YOUR_APP_NAME.YOUR_VARo req.mw_params.YOUR_VAR.

Le ayudará a evitar sobrescribir otros atributos.

Doron Segal avatar Feb 19 '2015 19:02 Doron Segal

El patrón más común para pasar variables a otros middleware y funciones de punto final es adjuntar valores al objeto de solicitud req.

En su caso, eso significaría tener middlewares como estos:

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

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

Hay muchos casos de uso comunes de este patrón y es la forma estándar de hacerlo en la comunidad express. Véase, por ejemplo:

  • express.json , que se envía con express, que anteriormente formaba parte de body-parser y que sigue el mismo patrón para todos los análisis de solicitudes.
  • Multer utilizado para analizar datos de varias partes.
  • expreso-jwt
  • validador expreso (ver código )
  • sesión-exprés
  • agente de usuario expreso
  • pinologger-expreso
  • registrador-expreso-bunyan

Vale la pena señalar que la respuesta más votada actualmente recomienda incorrectamente su uso res.localspara este propósito, lo que parece deberse a una mala lectura de la documentación. Por esa razón, explicaré por qué este no es el enfoque habitual para el problema (aunque tampoco es particularmente dañino).

La documentación

Como prueba de que el res.localsenfoque fue el adecuado para el caso, se cita la documentación ahora obsoleta :

Un objeto que contiene variables locales de respuesta con alcance para la solicitud y, por lo tanto, disponible solo para las vistas representadas durante ese ciclo de solicitud/respuesta (si corresponde). De lo contrario, esta propiedad es idéntica a app.locals.

Esta propiedad es útil para exponer información a nivel de solicitud, como el nombre de la ruta de la solicitud, el usuario autenticado, la configuración del usuario, etc.

Tenga en cuenta el marco aquí: res.localses para variables que solo están disponibles "para las vistas representadas durante esa solicitud " (énfasis agregado).

Eso es lo que res.localsse refiere. res.renderrepresenta algún archivo de plantilla con algunos datos dados, así como acceso a los locales. En realidad, esto quedó más claro en los documentos v2 y ahora hemos actualizado la documentación Express actual para que sea más claro:

Utilice esta propiedad para establecer variables accesibles en plantillas renderizadas con res.render. Las variables configuradas en res.locals están disponibles dentro de un único ciclo de solicitud-respuesta y no se compartirán entre solicitudes.

Para mantener las variables locales para usar en la representación de plantillas entre solicitudes, use app.locals en su lugar.

Esta propiedad es útil para exponer información a nivel de solicitud, como el nombre de la ruta de la solicitud, el usuario autenticado, la configuración del usuario, etc., en las plantillas representadas dentro de la aplicación.

(Énfasis añadido.)

La guía

Se encuentra más evidencia de que la extensión reqes el enfoque estándar en la guía sobre Escritura de Middleware , que establece:

A continuación, crearemos una función de middleware llamada "requestTime" y agregaremos una propiedad llamada requestTime al objeto de solicitud.

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

Cuando esto se mencionó en la discusión en las respuestas a esta pregunta, un usuario respondió: "Esta era la forma en que lo harías antes de que agregaran res.locals, por lo que podrían ser documentos antiguos. res.locals es un espacio de nombres específicamente para esto. "

Sin embargo, esto no coincide con el historial del código base: los locales han estado presentes desde la versión 2 , que es mucho antes de que, por ejemplo express.json, se incluyera en la biblioteca, momento en el que habría tenido sentido cambiar el comportamiento, si fuera realmente correcto. para guardar valores en res.locals.

Notas finales

Un saludo a @real_ate que escribió en los comentarios , pero fue pasado por alto.

Niels Abildgaard avatar Mar 15 '2022 18:03 Niels Abildgaard