I have the following route that basically acts on the post from a login form. The problem is that when the login is a success (member is found and the passwords match), the member._id is not stored in the session.
My route:
app.post('/signin', function(req, res) {
Member.findOne({username: req.body.username}, function(error, member) {
var matchPassword = crypto.createHmac('sha1', member.salt).update(req.body.password).digest('hex');
if(member.password == matchPassword) {
req.session.member_id = member._id;
res.redirect('/' + member.username);
}
});
res.redirect('/');
});
I get the following error in console when this route is fired:
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/Users/admin/Node Projects/sandboxProject/node_modules/express/node_modules/connect/lib/patch.js:62:20)
at ServerResponse.header (/Users/admin/Node Projects/sandboxProject/node_modules/express/lib/response.js:280:8)
at ServerResponse.redirect (/Users/admin/Node Projects/sandboxProject/node_modules/express/lib/response.js:413:10)
at Promise.<anonymous> (/Users/admin/Node Projects/sandboxProject/app.js:109:8)
at Promise.<anonymous> (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:120:8)
at Promise.<anonymous> (events.js:64:17)
at Promise.emit (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:59:38)
at Promise.complete (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:70:20)
at /Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/query.js:1087:15
It would seem that it didn't like the "res.redirect('/' + member.username);" after the "req.session.member_id = member._id;". Is this because of the asynchronous nature of the Mongoose findOne callback that it's in? I've tried removing the res.redirect from the callback but the session data is not stored and when I leave it in there, I get the "headers already sent" error.
My configuration:
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.cookieParser());
app.use(express.session({ secret: "blahblah" }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
I had a similar problem. Although my problem was that when I deleted something from session, e.g. delete req.session.user
, it would still be there after reloads and node app restarts. It would only be gone after req.session.destroy()
.
I looked at Node's session middleware docs and found that they have a Session#save()
method. So I did req.session.save()
after session object manipulations and it did fix my problem. Try it and see if it fixes yours.
The problem is that Member.findOne
is asynchronous. By the time its callback executes, the res.redirect('/')
has already executed, which sets the appropriate HTTP response headers. You can't send headers twice by HTTP rules, hence the error Can't set headers after they are sent.
You probably want to move the redirect('/')
into an else block of your password matching.
I had a similar problem. but my problem is at the time:
request.session.user = user;
I discovered through debug, When commenting out this line,This error does not occur:
// request.session.user = user;
this is my question: express 4.x session-mongoose Can't set headers after they are sent