我正在使用express在node.js中制作一个web应用程序。这是对我所拥有的东西的简化:

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中发送的数据不有效,我想向/页传递一些额外的上下文。我怎么能这样做呢?重定向似乎不允许任何类型的额外参数。


当前回答

我不得不寻找另一个解决方案,因为所提供的解决方案实际上没有一个满足我的要求,原因如下:

Query strings: You may not want to use query strings because the URLs could be shared by your users, and sometimes the query parameters do not make sense for a different user. For example, an error such as ?error=sessionExpired should never be displayed to another user by accident. req.session: You may not want to use req.session because you need the express-session dependency for this, which includes setting up a session store (such as MongoDB), which you may not need at all, or maybe you are already using a custom session store solution. next(): You may not want to use next() or next("router") because this essentially just renders your new page under the original URL, it's not really a redirect to the new URL, more like a forward/rewrite, which may not be acceptable.

所以这是我的第四个解决方案,没有任何前面的问题。基本上,它涉及到使用一个临时cookie,为此你必须首先安装cookie-parser。显然,这意味着它只能在启用cookie的情况下工作,并且数据量有限。

实现的例子:

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

其他回答

你可以通过查询字符串传递少量的键/值对数据:

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更改问题。

我不得不寻找另一个解决方案,因为所提供的解决方案实际上没有一个满足我的要求,原因如下:

Query strings: You may not want to use query strings because the URLs could be shared by your users, and sometimes the query parameters do not make sense for a different user. For example, an error such as ?error=sessionExpired should never be displayed to another user by accident. req.session: You may not want to use req.session because you need the express-session dependency for this, which includes setting up a session store (such as MongoDB), which you may not need at all, or maybe you are already using a custom session store solution. next(): You may not want to use next() or next("router") because this essentially just renders your new page under the original URL, it's not really a redirect to the new URL, more like a forward/rewrite, which may not be acceptable.

所以这是我的第四个解决方案,没有任何前面的问题。基本上,它涉及到使用一个临时cookie,为此你必须首先安装cookie-parser。显然,这意味着它只能在启用cookie的情况下工作,并且数据量有限。

实现的例子:

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("/");
}
 app.get('/category', function(req, res) {
  var string = query
  res.redirect('/?valid=' + string);
});

在ejs中,你可以直接使用valid:

<% var k = valid %>

下面是我的建议,不使用任何其他依赖,只是节点和表达式,使用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("/");
    }

有几种方法可以将数据传递到不同的路由。当然,最正确的答案是查询字符串。您需要确保这些值是正确的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核心模块为你生成查询字符串:

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

如果你使用的是节点>= 7。X你也可以使用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);
 });

另一种方法是在会话中设置一些内容。你可以在这里阅读如何设置它,但设置和访问变量是这样的:

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应用程序中传递信息。