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


Estoy usando express para hacer una aplicación web en node.js. Esta 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? Redirect no parece permitir ningún tipo de parámetro adicional.

Author: mikemaccana, 2013-09-26

4 answers

Hay algunas formas de pasar datos a diferentes rutas. La respuesta más correcta es, por supuesto, las cadenas de consulta. Tendrá que asegurarse de que los valores son correctamente encodeURIComponenty decodeURIComponent.

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

Puede engancharlo 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 utilizar el url módulo core 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"
        }
     }));
 });

Así que si desea redirigir todas las variables de cadena de consulta req, simplemente puede hacer

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

Y si está utilizando Node >= 7.x también puede utilizar el querystring módulo básico

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 configurando algo en la sesión. Puedes leer cómo configurarlo aquí , pero establecer y acceder a 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 característica antigua de Express, req.flash. Hacerlo en versiones más recientes de Express requerirá que utilice otra biblioteca. Esencialmente 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 añade esta funcionalidad.

Esperemos que eso le dé una idea general de cómo pasar información en una aplicación Express.

 250
Author: Dropped.on.Caprica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 12:19:20

La forma más fácil que he encontrado para pasar datos entre routeHandlers para usar next() no hay necesidad de meterse con redireccionamiento o sesiones. Opcionalmente, puede llamar a su homeCtrl(req,res) en lugar de next() y simplemente pasar el 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);
 30
Author: jqualls,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-01 15:05:31

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

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

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

Tenga en cuenta que si no le importa /category permanecer como la URL en la barra de direcciones del navegador, solo puede renderizar directamente en lugar de redirigir. En mi humilde opinión muchas veces las personas usan redirecciones porque los marcos web antiguos hacían difícil responder directamente, pero es fácil en express:

app.post('/category', function(req, res) {

  // Process the data received in req.body

  res.render('home.jade', {error: 'denied'});
});

As @Dropped.en.Caprica comentado, el uso de AJAX elimina la preocupación de cambio de URL.

 2
Author: Peter Lyons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-26 21:26:13

Tuve que encontrar otra solución porque ninguna de las soluciones proporcionadas realmente cumplía mis requisitos, por las siguientes razones:

  • Cadenas de consulta : Es posible que no desee usar cadenas de consulta porque las URL podrían ser compartidas por sus usuarios, y a veces los parámetros de consulta no tienen sentido para un usuario diferente. Por ejemplo, un error como ?error=sessionExpired nunca debe mostrarse a otro usuario por accidente.

  • Req.sesión : Puede que no quieras usar req.session porque necesita la dependencia express-session 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 almacén de sesiones personalizada.

  • Next(): Es posible que no desee usar next() o next("router") porque esto esencialmente solo representa su nueva página bajo la URL original, no es realmente un redireccionamiento a la nueva URL, más como un reenvío / reescritura, que puede no ser aceptable.

Así que esta es mi cuarta solución que no sufre de ninguno de los problemas anteriores. Básicamente implica el uso de una cookie temporal, para lo cual primero tendrá que instalar cookie-parser. 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("/");
}
 0
Author: cprcrack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-30 17:06:42