【问题标题】:Express: unable to access POST data and set cookie at the same timeExpress:无法同时访问POST数据和设置cookie
【发布时间】:2017-06-03 11:38:15
【问题描述】:

我正在编写一个应用程序,它接受一个发布请求并设置一个从 POST 信息中提取的 cookie。我陷入了第 22 个问题。在第一个代码示例中,我可以设置 cookie 但无法访问数据,在第二个代码示例中,我可以访问数据但无法设置 cookie。我确定我错过了中间件如何工作的一些基本概念,但我无法终生找到我需要的信息。

下面的代码按预期创建了 cookie,但我的 post 变量未定义

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , handshake = require('./routes/handshake')
  , http = require('http')
  , path = require('path');

var app = express();   
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride()); 
app.use(function (req, res, next) {
    var cookie = req.cookies.cokkieName;
    console.log("cookie_name" , cookie);
    if (cookie === undefined)
    {
            //cookie is set but I can't use req.post.xxxx. It"s always undefined
        res.cookie("price", 111, { maxAge: 10000 });
        console.log('cookie has been created successfully');
    } 
    else
    {
        console.log('cookie exists', cookie);
    } 
    next();
});

app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
app.post('/handshake', handshake.token);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

以下代码执行 setCookie 回调(因为显示了控制台输出),并且在控制台上正确定义了变量,但未设置 cookie。

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , handshake = require('./routes/handshake')
  , http = require('http')
  , path = require('path');

var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());


var setCookie = function (req, res, next) {
    var cookie = req.cookies.cokkieName;
    console.log("cookie_name" , cookie);
    if (cookie === undefined)
    {

        res.cookie("price", 111, { maxAge: 10000 }); 
            //in the console the post.body.xxxx data appears correctly but no cookie!!!
        console.log('cookie has been created successfully',post.body.xxx);
    } 
    else
    {
        console.log('cookie exists', cookie);
    } 
    next();
};
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
app.post('/handshake', setCookie ,handshake.token);
http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

为了使代码更具可读性,引入了太多与我的代码无关的错别字。我接受了这个建议并按以下方式更改了代码,但它仍然没有向客户端写入 cookie。

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , handshake = require('./routes/handshake')
  , http = require('http')
  , crypt = require('crypto')
  , io = require('socket.io')
  , db = require('levelup')('./mydb')
  , path = require('path');

var app = express();
app.use(express.cookieParser());
app.use(express.bodyParser());

var cookieMiddleware = function (req, res, next) {
    var cookie = req.cookies.user;
    console.log("cookie_name" , cookie);
    if (cookie === undefined)
    {
        // no: set a new cookie
        var random = Math.random().toString();
        random=random.substring(2,random.length);       
        sessionToken = Date.now()  + random;
        salt = sessionToken + req.body.address;
        sha2 = crypt.createHash('sha256');
        sha2.update(sessionToken);
        var price = req.body.price;
        var encryptedSession = sha2.digest('hex');

    console.log('post body',price );
        res.cookie('user','price' , { maxAge: 100000 });
        console.log('existing cookies', req.cookies);
    } 
    else
    {
        console.log('cookie exists', req.cookies);
    } 
    next(); 
};
//development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}

app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger('dev'));
app.use(express.session({secret: "TheSuperSecretStringForHashing"}));
app.use(express.methodOverride());
app.use(app.router);
//app.use(express.favicon());
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
app.post('/handshake', cookieMiddleware , handshake.token);
app.get('/', routes.index);
app.get('/users', user.list);


 var server = http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

io = io.listen(server);

io.sockets.on('connection', function (socket) {
      socket.emit('news', { hello: 'world' });
      socket.on('my other event', function (data) {
        console.log(data);
      });
    });

handshake.js 处理程序

exports.token = function(req, res){
    req.body.title = 'Payment Portal';
    res.render('payment_init', req.body);
};

【问题讨论】:

  • 我只是简单地扫描了代码,但由于您使用全局中间件作为 cookie,是否有其他请求在发布请求之前设置它?例如,一个网站图标请求也由全局中间件处理,除非您在 cookie 中间件之前结束该请求。这与您应该将静态中间件放在顶部的原因相同(您没有这样做)。因此,对于静态文件,您的 cookie 中间件也在运行。如果你只想在 '/handshake' 路由上运行 cookie 中间件,你可以做 app.post('/handskake', cookieMiddleware, handskake.token)。
  • 嗨@Pickels 感谢您的回复。我很难理解你的几点。 “...一个网站图标请求也由全局中间件处理,除非您在 cookie 中间件之前结束该请求”。实际上,我确实在 cookie 之前有全局 favicon(我将其删除以使代码更具可读性),但我不清楚您所说的“结束该请求”是什么意思。此外,“对于静态文件,您的 cookie 中间件也在运行。”。我不清楚为什么这很糟糕。如果它使用静态文件运行,则应设置 cookie。这不是我想要的吗?提前致谢。
  • 我注意到的另一件事是你使用 req.post.xxx 它应该是 req.body.xxx。使用“结束该请求”我的意思是,如果中间件做到了,那么下面的中间件不必处理任何其他事情,它将结束请求并且不调用下一个。因此,在静态中间件的情况下,当它发现您的 url 与磁盘上的文件匹配时,它将提供该文件而不是下一个调用。这样您就不会运行与提供静态文件无关的额外中间件。
  • @Pickels,我采纳了您的建议并将代码更改为以下 app.post('/handshake', cookieMiddleware , handshake.token); cookieMiddleware 函数被执行,我可以读取 req.body.price 变量(可以在控制台中看到它)但是 cookie 仍然没有被发送到客户端。此外,当我在设置 cookie 后立即执行 console.log(res) 时,我可以看到这个 _headers: { 'x-powered-by': 'Express', 'set-cookie': 'user=price;最大年龄=100;路径=/; Expires=Sat, 27 Apr 2013 05:01:54 GMT' } 那么为什么 cookie 没有显示在客户端上?
  • @user1822910 你没有在handshake.token 的某个地方使用res.writeHead,是吗?

标签: node.js cookies express


【解决方案1】:

您正在检查名为 cokkieName 的 cookie,但您设置的 cookie 的名称为 price

尝试将其更改为:

var cookie = req.cookies.price;

cookie 现在应该包含您的 cookie 值。

【讨论】:

  • 是的,这是一个错字,但它仍然不能解释为什么我无法访问帖子数据。我很确定 Pickles 对我的问题的回答解释了发生的事情,但我仍在阅读文档,试图完全理解他的答案。
猜你喜欢
  • 2017-07-05
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-30
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
相关资源
最近更新 更多