web-dev-qa-db-fra.com

Comment puis-je rediriger dans expressjs en passant du contexte?

J'utilise express pour créer une application Web dans node.js. Ceci est une simplification de ce que j'ai:

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('/');
});

Mon problème est le suivant:

Si je constate que les données envoyées dans /category ne sont pas validées, j'aimerais passer un contexte supplémentaire à la page /. Comment pourrais-je faire ça? La redirection ne semble autoriser aucun type de paramètre supplémentaire.

184
Enrique Moreno Tent

Il existe quelques moyens de transmettre des données à différents itinéraires. La réponse la plus correcte est, bien sûr, les chaînes de requête. Vous devez vous assurer que les valeurs sont correctement encodeURIComponent et decodeURIComponent .

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

Vous pouvez accrocher cela dans votre autre route en récupérant les paramètres envoyés en utilisant req.query.

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

Pour plus dynamique, vous pouvez utiliser le module url core pour générer la chaîne de requête pour vous:

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

Donc, si vous voulez rediriger toutes les variables de chaîne de requête req, vous pouvez simplement le faire 

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

Et si vous utilisez Node> = 7.x, vous pouvez également utiliser le module querystring core

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);
 });

Une autre façon de le faire est d’organiser quelque chose dans la session. Vous pouvez lire comment le configurer ici , mais définir et accéder aux variables ressemble à ceci:

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

Et plus tard, après la redirection ...

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

Il existe également la possibilité d'utiliser une ancienne fonctionnalité d'Express, req.flash. Dans les nouvelles versions d'Express, vous devrez utiliser une autre bibliothèque. Essentiellement, cela vous permet de configurer des variables qui apparaîtront et se réinitialiseront la prochaine fois que vous irez sur une page. C'est pratique pour montrer les erreurs aux utilisateurs, mais encore une fois, il a été supprimé par défaut. EDIT: Trouvé une bibliothèque qui ajoute cette fonctionnalité.

J'espère que cela vous donnera une idée générale de la manière de transmettre des informations dans une application Express.

273
AlbertEngelB

Le moyen le plus simple que j'ai trouvé pour transmettre des données entre routeHandlers consiste à utiliser next() sans avoir à manipuler les redirections ni les sessions . Vous pouvez éventuellement appeler votre homeCtrl(req,res) au lieu de next() et simplement passer les req et 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);
33
jqualls

Voici ce que je suggère sans utiliser aucune autre dépendance, juste node et express, utilisez app.locals, voici un exemple:

    app.get("/", function(req, res) {
        var context = req.app.locals.specialContext;
        req.app.locals.specialContext = null;
        res.render("home.jade", context); 
        // or if you are using ejs
        res.render("home", {context: context}); 
    });

    function middleware(req, res, next) {
        req.app.locals.specialContext = * your context goes here *
        res.redirect("/");
    }
2
Hussein Dimessi

Vous pouvez transmettre de petits bits de données de paire clé/valeur via la chaîne de requête:

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

Et javascript sur la page d'accueil peut accéder à cela et ajuster son comportement en conséquence.

Notez que si /category ne craint pas de rester en tant qu'URL dans la barre d'adresse du navigateur, vous pouvez simplement effectuer le rendu directement au lieu de la redirection. À mon humble avis, les gens utilisent souvent des redirections parce que les anciens frameworks Web rendaient la réponse directe difficile, mais c'est facile dans express:

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

  // Process the data received in req.body

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

Comme @ Dropped.on.Caprica a commenté, l'utilisation de AJAX élimine le problème de modification de l'URL.

2
Peter Lyons

J'ai dû trouver une autre solution car aucune des solutions fournies ne répondait réellement à mes exigences, pour les raisons suivantes:

  • Chaînes de requête: vous souhaiterez peut-être ne pas utiliser de chaînes de requête car les URL pourraient être partagées par vos utilisateurs. Par conséquent, les paramètres de requête n'ont parfois aucun sens pour un utilisateur différent. Par exemple, une erreur telle que ?error=sessionExpired ne doit jamais être affichée par accident à un autre utilisateur.

  • req.session: vous voudrez peut-être ne pas utiliser req.session car vous avez besoin de la dépendance express-session , qui inclut la configuration d'un magasin de sessions (tel que MongoDB), dont vous n'avez peut-être pas besoin , ou peut-être utilisez-vous déjà une solution de magasin de session personnalisée.

  • next (): Vous ne voudrez peut-être pas utiliser next() ou next("router") car cela ne fait que rendre votre nouvelle page sous l'URL d'origine. être acceptable.

C'est donc ma quatrième solution qui ne souffre d'aucun des problèmes précédents. Fondamentalement, cela implique l’utilisation d’un cookie temporaire, pour lequel vous devrez d’abord installer cookie-parser . Évidemment, cela signifie que cela ne fonctionnera que si les cookies sont activés et avec une quantité de données limitée.

Exemple d'implémentation:

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("/");
}
1
cprcrack

L'une des solutions consiste à utiliser le middleware d'analyse syntaxique du corps et à transmettre les données sous forme d'objet JSON.

var express = require('express');
var jade = require('jade');
var http = require("http");
const bodyParser = require('body-parser') //requiring body parser 


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
  //pass the data as an json object 
  res.redirect('/', { data: data });
});

Vous pouvez utiliser cet objet de données dans la page accessible via ce chemin '/'.

0
Hadi Mir