¿Cómo redirecciono en expressjs mientras paso algún contexto?

Estoy usando express para hacer una aplicación web en node.js. Esto es una simplificación de lo que tengo:

var express = require('express'); var jade = require('jade'); var http = require("http"); var app = express(); var server = http.createServer(app); app.get('/', function(req, res) { // Prepare the context res.render('home.jade', context); }); app.post('/category', function(req, res) { // Process the data received in req.body res.redirect('/'); }); 

Mi problema es el siguiente:

Si encuentro que los datos enviados en /category no se validan, me gustaría pasar algún contexto adicional a la / página. ¿Cómo podría hacer esto? Redirigir no parece permitir ningún tipo de parámetro extra.

Hay algunas formas de pasar datos a diferentes rutas. La respuesta más correcta es, por supuesto, cadenas de consulta. Deberá asegurarse de que los valores sean los adecuados encodeURIComponent y decodeURIComponent .

 app.get('/category', function(req, res) { var string = encodeURIComponent('something that would break'); res.redirect('/?valid=' + string); }); 

Puede enganchar eso en su otra ruta obteniendo los parámetros enviados usando req.query .

 app.get('/', function(req, res) { var passedVariable = req.query.valid; // Do something with variable }); 

Para una forma más dinámica puede usar el módulo de núcleo de url para generar la cadena de consulta para usted:

 const url = require('url'); app.get('/category', function(req, res) { res.redirect(url.format({ pathname:"/", query: { "a": 1, "b": 2, "valid":"your string here" } })); }); 

Entonces, si quiere redirigir todas las variables de cadena de consulta de consulta, simplemente puede hacer

 res.redirect(url.format({ pathname:"/", query:req.query, }); }); 

Y si está utilizando Node> = 7.x, también puede usar el módulo core querystring

 const querystring = require('querystring'); app.get('/category', function(req, res) { const query = querystring.stringify({ "a": 1, "b": 2, "valid":"your string here" }); res.redirect('/?' + query); }); 

Otra forma de hacerlo es establecer algo en la sesión. Puede leer cómo configurarlo aquí , pero establecer y acceder a las variables es algo como esto:

 app.get('/category', function(req, res) { req.session.valid = true; res.redirect('/'); }); 

Y más tarde después de la redirección …

 app.get('/', function(req, res) { var passedVariable = req.session.valid; req.session.valid = null; // resets session variable // Do something }); 

También existe la opción de usar una función antigua de Express, req.flash . Hacerlo en versiones más nuevas de Express requerirá que use otra biblioteca. Básicamente, le permite configurar variables que se mostrarán y restablecerán la próxima vez que vaya a una página. Es útil para mostrar errores a los usuarios, pero de nuevo se ha eliminado por defecto. EDITAR: se encontró una biblioteca que agrega esta funcionalidad.

Con suerte, eso le dará una idea general sobre cómo pasar información en una aplicación Express.

La forma más fácil que he encontrado para pasar datos entre los manejadores de ruta para usar next() no es necesario meterse con la redirección o las sesiones. Opcionalmente, puede llamar a su homeCtrl(req,res) lugar de a next() y simplemente pasar la req y res

 var express = require('express'); var jade = require('jade'); var http = require("http"); var app = express(); var server = http.createServer(app); ///////////// // Routing // ///////////// // Move route middleware into named // functions function homeCtrl(req, res) { // Prepare the context var context = req.dataProcessed; res.render('home.jade', context); } function categoryCtrl(req, res, next) { // Process the data received in req.body // instead of res.redirect('/'); req.dataProcessed = somethingYouDid; return next(); // optionally - Same effect // accept no need to define homeCtrl // as the last piece of middleware // return homeCtrl(req, res, next); } app.get('/', homeCtrl); app.post('/category', categoryCtrl, homeCtrl); 

Puede pasar pequeños bits de datos de par clave / valor a través de la cadena de consulta:

 res.redirect('/?error=denied'); 

Y javascript en la página de inicio puede acceder a eso y ajustar su comportamiento en consecuencia.

Tenga en cuenta que si no le importa que la /category permanezca como URL en la barra de direcciones del navegador, puede procesar directamente en lugar de redirigir. En mi humilde opinión, muchas veces las personas usan redirecciones porque los marcos web más antiguos hacen que la respuesta directa sea difícil, pero es fácil de express:

 app.post('/category', function(req, res) { // Process the data received in req.body res.render('home.jade', {error: 'denied'}); }); 

Como comentó @ Dropped.on.Caprica, el uso de AJAX elimina la preocupación por el cambio de URL.

Tenía que encontrar otra solución porque ninguna de las soluciones proporcionadas en realidad cumplía con mis requisitos, por las siguientes razones:

  • Cadenas de consulta : es posible que no desee utilizar cadenas de consulta porque los URL podrían compartirlas los usuarios y, a veces, los parámetros de consulta no tienen sentido para un usuario diferente. Por ejemplo, un error como ?error=sessionExpired nunca se debe mostrar a otro usuario por accidente.

  • req.session : es posible que no desee utilizar req.session porque necesita la dependencia de la sesión expresa para esto, que incluye la configuración de un almacén de sesiones (como MongoDB), que puede que no necesite en absoluto, o tal vez ya esté utilizando una solución de tienda de sesión personalizada.

  • siguiente () : es posible que no desee utilizar el next() o next("router") porque esto básicamente solo representa su nueva página debajo de la URL original, no es realmente un redireccionamiento a la nueva URL, más bien como un reenvío / reescritura, que puede no ser aceptable.

Entonces esta es mi cuarta solución que no sufre ninguno de los problemas anteriores. Básicamente, implica el uso de una cookie temporal, para lo cual deberá instalar primero el analizador de cookies . Obviamente, esto significa que solo funcionará cuando las cookies estén habilitadas y con una cantidad limitada de datos.

Ejemplo de implementación:

 var cookieParser = require("cookie-parser"); app.use(cookieParser()); app.get("/", function(req, res) { var context = req.cookies["context"]; res.clearCookie("context", { httpOnly: true }); res.render("home.jade", context); // Here context is just a string, you will have to provide a valid context for your template engine }); app.post("/category", function(req, res) { res.cookie("context", "myContext", { httpOnly: true }); res.redirect("/"); }