Сессии не будут сохраняться в Node.js без req.session.save()

Я создаю веб-сайт с использованием Node.js, Express и Redis для управления сеансами. По какой-либо причине, если у меня есть переменная сеанса (isLoggedIn в этом примере), и я isLoggedIn страницу, переменная не будет сохранена, однако, если я вызову req.session.save() после установки переменной, она будет сохранить в Redis (монитор redis-cli показывает это - не вызов save() показывает, что переменной нет, а вызов save() показывает ее).

Я использую это, чтобы настроить и запустить сервер:

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

И затем, в этом маршруте, у меня есть:

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;

Из этого я должен быть в состоянии перейти к /login, установить для сеанса isLoggedIn значение true, и это должно автоматически сэкономить на Redis. После этого, заголовок / должен сказать мне, что я вошел в систему. Loading /login задает переменную, второй журнал показывает это, но загружает / говорит, что я не вошел в систему. Redis-cli monitor показывает

1414076171.241836 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"}}"

при сохранении, которое не включает переменную isLoggedIn, но добавление в req.session.save() показывает:

1414076475.601644 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"},\"isLoggedIn\":true}"

Любая идея о том, почему я должен вызвать req.session.save() когда все примеры, которые я видел, не используют его?

Ответы

Ответ 1

Итак, я понял это. Я отвечу здесь всем, кто попадает на это.

Для запросов GET сервер предполагает, что вы собираетесь отправлять данные, и автоматически сохраняет данные сеанса после того, как маршрут будет полностью обработан.

Однако для запросов POST (то, что я использую) такое же предположение не выполняется. Состояние сеанса сохраняется только в одном из двух условий - либо при отправке данных (через res.send, res.redirect и т.д.), req.session.save() вызове вручную req.session.save(). Я уже звонил/выходил из запроса AJAX, я просто ничего не возвращал, если были выполнены определенные условия. После того, как сервер ответит клиенту с некоторыми данными после установки переменной сеанса, это исправлено.