web-dev-qa-db-ja.com

コンテキストを渡しながら、expressjsにリダイレクトするにはどうすればよいですか?

Node.jsでWebアプリケーションを作成するためにexpressを使用しています。これは私が持っているものを単純化したものです。

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

私の問題は以下の通りです:

/categoryで送信されたデータが検証されないことがわかった場合は、追加のコンテキストを/ページに渡します。どうすればいいの?リダイレクトはいかなる種類の追加パラメータも許可しないようです。

205

異なる経路にデータを渡す方法はいくつかあります。最も正しい答えは、もちろん、クエリ文字列です。値が正しく encodeURIComponent および decodeURIComponent であることを確認する必要があります。

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

req.queryを使用して送信されたパラメータを取得することによって、他の経路でそれを盗むことができます。

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

より動的な方法では、 url coreモジュールを使ってクエリ文字列を生成することができます。

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

あなたがすべてのreqクエリ文字列変数をリダイレクトしたいのであればあなたは単にすることができます

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

もしNode> = 7.xを使っているのなら、 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);
 });

それを行う別の方法は、セッションで何かを設定することです。 ここで設定方法を読むことができます しかし、変数を設定してアクセスするのは次のようなものです。

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

そして後でリダイレクトの後に...

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

Expressの古い機能であるreq.flashを使用するというオプションもあります。新しいバージョンのExpressでこれを行うには、別のライブラリを使用する必要があります。基本的にそれはあなたが表示され、あなたが次にページに行くときリセットされる変数を設定することを可能にします。ユーザーにエラーを表示するのに便利ですが、やはりデフォルトで削除されています。編集: この機能を追加するライブラリを見つけました。

うまくいけば、Expressアプリケーションで情報をやり取りする方法の一般的なアイデアがわかります。

293
AlbertEngelB

next()を使用するためにrouteHandler間でデータをやり取りするための最も簡単な方法は、リダイレクトやセッションを台無しにする必要はありません。必要に応じて、homeCtrl(req,res)の代わりにnext()を呼び出し、reqresを渡すこともできます。

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);
34
jqualls

以下の理由から、提供されているソリューションのどれも実際には要件を満たしていないため、別のソリューションを探す必要がありました。

  • クエリ文字列 :URLはユーザーによって共有される可能性があるため、クエリ文字列を使用したくない場合があります。また、クエリパラメータが別のユーザーにとって意味がない場合もあります。たとえば、?error=sessionExpiredなどのエラーは、誤って他のユーザーに表示されることはありません。

  • req.session :これには express-session 依存関係が必要なため、req.sessionを使用したくない場合があります。これには、セッションストア(MongoDBなど)の設定が含まれます。まったく、または多分あなたは既にカスタムセッションストアソリューションを使用しています。

  • next() :これは基本的に新しいページを元のURLの下に表示するだけなので、next()next("router")を使用したくない場合があります。転送/書き換えのような新しいURLへのリダイレクトではありません。受け入れられないかもしれません。

それで、これは私の4番目の解決策で、これまでの問題のどれにも悩まされていません。基本的にそれはあなたが最初に cookie-parser をインストールしなければならない一時的なクッキーの使用を含みます。明らかにこれはクッキーが有効になっている場合に限られた量のデータでのみ機能することを意味します。

実装例:

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

これは私が他の依存関係を使わずに提案するものです。ただnodeとexpressを使い、app.localsを使ってください、これは例です:

    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

クエリ文字列を介して、小さい値のキー/値ペアデータを渡すことができます。

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

そしてホームページ上のjavascriptがそれにアクセスし、それに応じてその振る舞いを調整することができます。

/categoryをブラウザのアドレスバーのURLとして使用しても構わない場合は、リダイレクトする代わりに直接レンダリングすることができます。古いWebフレームワークでは直接応答するのが困難だったため、私見は何度も人がリダイレクトを使用しますが、表現は簡単です。

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

  // Process the data received in req.body

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

@ Dropped.on.Capricaがコメントしたように、AJAXを使用すると、URLの変更の心配がなくなります。

2
Peter Lyons

解決策の1つは、ボディパーサーミドルウェアであり、データを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 });
});

このデータオブジェクトは、この'/'パスを通じてアクセスされるページで使用できます。

0
Hadi Mir