Sessions won't save in Node.js without req.session.save()
Okay, so, I've figured it out. I'll put the answer here for anyone else that happens to get caught on this.
For GET requests, the server assumes that you're going to be sending data back, and will automatically save session data once the route is fully processed.
For POST requests (what I'm using), however, the same assumption isn't made. Session states are only saved in one of two conditions - either when data is being sent out (through res.send
, res.redirect
, etc.), or if you manually call req.session.save()
. I was already calling /login from an AJAX request, I just wasn't returning anything if certain conditions were met. Having the server respond to the client with some data after setting the session variable fixed this.
PuppyKevin
Updated on October 04, 2020Comments
-
PuppyKevin over 3 years
I'm building a website using Node.js, Express, and Redis for session management. For whatever reason, if I have a session variable (
isLoggedIn
in this example), and I refresh the page, the variable doesn't get saved, however, if I callreq.session.save()
after setting the variable, it does get saved to Redis (redis-cli monitor shows this - not callingsave()
shows that the variable isn't there, whereas callingsave()
shows it).I'm using this to set up and start the server:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var swig = require('swig'); var session = require('express-session') var RedisStore = require('connect-redis')(session); var routes = require('./routes/index'); var users = require('./routes/users'); var app = express(); // Configure the favicon first. This avoids other middleware from processing the request if we know the request is for the favicon. app.use(favicon(__dirname + '/public/images/favicon.ico')); // All other requests will require everything else. // Set up the view engine. app.set('view engine', 'html'); app.set('views', path.join(__dirname, '/views')); app.engine('html', swig.renderFile); // Set up our logger. app.use(logger('dev')); // Set up JSON parsing. app.use(bodyParser.json()); // Set up encoded URL parsing. app.use(bodyParser.urlencoded()); // Set up the cookie parser. app.use(cookieParser('thedogsleepsatnight')); // Set up our session store. This will use Redis as our session management. app.use(session({ resave: true, saveUninitialized: true, secret: "thedogsleepsatnight", store: new RedisStore() })); app.use(require('stylus').middleware(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', routes);
And then, in that route, I have:
var express = require('express'); var router = express.Router(); router.get('/', function(req, res) { console.log(req.session.isLoggedIn); if (req.session.isLoggedIn) { console.log("Logged in!"); } else { console.log("Not logged in"); } res.render('index'); }); router.post('/login', function(req, res) { console.log("Going to set isLoggedIn. Currently: " + req.session.isLoggedIn); req.session.isLoggedIn = true; console.log("Set isLoggedIn. Currently: " + req.session.isLoggedIn); }); module.exports = router;
From that, I should be able to navigate to
/login
, have the session set isLoggedIn to true, and that should save automatically to Redis. After that, heading to/
should tell me that I'm logged in. Loading/login
does set the variable, the second log shows that, but loading/
says that I'm not logged in. redis-cli monitor shows1414076171.241836 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"}}"
upon saving, which doesn't include the
isLoggedIn
variable, but adding inreq.session.save()
shows:1414076475.601644 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"},\"isLoggedIn\":true}"
Any idea on why I have to call
req.session.save()
when all of the examples I've seen don't use it?