It is possible for back-to-back requests to be missing session data.
Say you have a webapp with 2 routes. Route /a stores a value in the session and then redirects to route /b. Route /b simply prints the value stored in the session. If the session store is slow, it is possible to hit route /b before the session is persisted. express-session starts writing a response back to the browser in writetop() before the session is persisted. once the session data is persisted, express-session calls writeend(). When express-session executes writetop(), the browser gets the 302 redirect and performs the get on route /b before the session data is persisted. When route /b prints its session data, the stored value is not there. I believe express-session should not perform writetop() and only call writeend() once the session data is persisted.
Webapp:
/a
req.session.key = 'value';
res.redirect("/b")
/b
console.log(req.session.key)
A sample log file would like this:
GET /a
GET /b
Most of the time the session data is persisted before the request for /b and everything proceeds as expected, but once in a while the request for /b will arrive before the session data is persisted causing problems.
To get around this problem, I removed the writetop() from index.js and fixed up the if logic:
// touch session
req.session.touch();
if (shouldSave(req)) {
req.session.save(function onsave(err) {
if (err) {
defer(next, err);
}
return writeend();
});
} else if (storeImplementsTouch && shouldTouch(req)) {
// store implements touch method
debug('touching');
store.touch(req.sessionID, req.session, function ontouch(err) {
if (err) {
defer(next, err);
}
debug('touched');
writeend();
});
return writetop();
} else {
return _end.call(res, chunk, encoding);
}
When you are performing a redirect, you must call req.session.save(cb) yourself and then send the redirect from the cb; modern web browsers ignore the body of the response and so start loading the destination page well before we finished sending the response to the client.
Example:
req.session.save(function (err) {
if (err) return next(err)
res.redirect('/b')
})
P.S. a user submitted the PR #157 to attempt to fix this, but it seems to have stalled out if you want to pick it up and continue working to address the issues raised there.
Most helpful comment
When you are performing a redirect, you must call
req.session.save(cb)yourself and then send the redirect from thecb; modern web browsers ignore the body of the response and so start loading the destination page well before we finished sending the response to the client.