330

我正在使用 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未验证,我想将一些额外的上下文传递给/页面。我怎么能这样做?重定向似乎不允许任何类型的额外参数。

4

10 回答 10

451

有几种方法可以将数据传递到不同的路由。最正确的答案当然是查询字符串。您需要确保值正确encodeURIComponentdecodeURIComponent

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

如果你使用 Node >= 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 应用程序中传递信息。

于 2013-09-26T20:26:54.177 回答
50

我发现在 routeHandlers 之间传递数据的最简单方法是使用next()不需要搞乱重定向或会话。或者,您可以只调用您的homeCtrl(req,res)而不是,next()然后通过reqandres

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);
于 2014-07-01T15:05:31.517 回答
16

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

  • 查询字符串:您可能不想使用查询字符串,因为您的用户可能会共享 URL,而且有时查询参数对其他用户没有意义。例如,?error=sessionExpired永远不应向其他用户意外显示错误。

  • req.session:您可能不想使用req.session,因为您需要express-session依赖项,其中包括设置会话存储(例如 MongoDB),您可能根本不需要,或者您可能已经在使用自定义会话存储解决方案。

  • next():您可能不想使用next(),或者next("router")因为这实际上只是在原始 URL 下呈现您的新页面,它并不是真正重定向到新 URL,更像是转发/重写,这可能是不可接受的。

所以这是我的第四个解决方案,它不受任何先前问题的影响。基本上它涉及使用临时 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("/");
}
于 2018-08-30T17:06:42.530 回答
10

使用 app.set & app.get

设定数据

router.get(
  "/facebook/callback",
  passport.authenticate("facebook"),
  (req, res) => {
    req.app.set('user', res.req.user)
    return res.redirect("/sign");
  }
);

获取数据

router.get("/sign", (req, res) => {
  console.log('sign', req.app.get('user'))
});

于 2019-11-21T04:03:27.257 回答
6

我们可以使用express-session发送所需的数据

当您初始化应用程序时

const express = require('express');
const app = express();
const session = require('express-session');
app.use(session({secret: 'mySecret', resave: false, saveUninitialized: false}));

所以在重定向之前只需保存会话的上下文

app.post('/category', function(req, res) {
    // add your context here 
req.session.context ='your context here' ;
    res.redirect('/');
});

现在您可以在任何地方获取会话的上下文。它可以通过req.session.context获得

app.get('/', function(req, res) {

    // So prepare the context
var context=req.session.context;
    res.render('home.jade', context);
});
于 2020-03-10T15:16:38.587 回答
5

这是我不使用任何其他依赖项的建议,只需 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("/");
    }
于 2019-03-16T13:44:59.457 回答
3

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

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

于 2013-09-26T20:16:47.613 回答
0

2021 年更新:我试过了url.formatquerystring但它们都已弃用,我们可以使用URLSearchParams

const {URLSearchParams} = require('url')
               
app.get('/category', (req, res) =>{
    const pathname = '/?'
    const components ={
    a:"a",
    b:"b"
}

    const urlParameters = new URLSearchParams(components)
    res.redirect(pathname + urlParameters)
})
于 2021-11-23T15:02:22.430 回答
-1

我在我的app.js (我的入口点)中使用了一种非常简单但有效的技术 我定义了一个变量,例如

let authUser = {};

然后我从我的路由页面分配给它(比如成功登录后)

authUser = matchedUser

这可能不是最好的方法,但它符合我的需要。

于 2021-01-06T07:59:03.427 回答
-3
 app.get('/category', function(req, res) {
  var string = query
  res.redirect('/?valid=' + string);
});

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

<% var k = valid %>
于 2020-08-10T18:30:14.130 回答