Pasar variables al siguiente middleware usando next() en Express.js
Quiero pasar alguna variable del primer middleware a otro middleware, e intenté hacer esto, pero había " req.somevariable
un valor dado como 'indefinido'".
//app.js
..
app.get('/someurl/', middleware1, middleware2)
...
////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...
////middleware2
...
some conditions
...
variable = req.somevariable;
...
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();
});
Adjunte su variable al res.locals
objeto, no req
.
En lugar de
req.somevariable = variable1;
Tener:
res.locals.somevariable = variable1;
Como otros han señalado, res.locals
es la forma recomendada de pasar datos a través de middleware.
No creo que la mejor práctica sea pasar una variable como req.YOUR_VAR
. Quizás quieras considerar req.YOUR_APP_NAME.YOUR_VAR
o req.mw_params.YOUR_VAR
.
Le ayudará a evitar sobrescribir otros atributos.
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.locals
para 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.locals
enfoque 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.locals
es para variables que solo están disponibles "para las vistas representadas durante esa solicitud " (énfasis agregado).
Eso es lo que res.locals
se refiere. res.render
representa 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 req
es 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.