Node.js & Экспресс-сессия

У меня проблема с сеансами, где иногда переменная сеанса, которую я только что установил undefined в запросе следующей страницы. Мне обычно приходится проходить через поток снова, чтобы правильно установить переменные.

Я могу подтвердить, что я не пытаюсь установить переменные сеанса на undefined; они имеют законное значение.

В моем приложении пользователи переходят из /twitter/connect/to/twitter/callback/. Первый извлекает некоторые данные oauth из twitter, последний регистрирует пользователя в твиттере.

/twitter/connect/просто:

app.get('/twitter/connect/?', function(req, res){
    consumer().getOAuthRequestToken(function(error, oauthToken, oauthTokenSecret, results){
        if (error){
            // error handling here
        } else {
            req.session.oauthRequestToken = oauthToken;
            req.session.oauthRequestTokenSecret = oauthTokenSecret;

            // if I console.log the two session variables above
            // they have the proper values.

            res.redirect("https://twitter.com/oauth/authorize?oauth_token="+req.session.oauthRequestToken);      
        }
    });
});

После этого твиттер отправляет их обратно в /twitter/callback/:

app.get('/twitter/callback/?', function(req, res){
    console.log(req.session.oauthRequestToken);
    console.log(req.session.oauthRequestTokenSecret);

    // more often than not, the two variables above are
    // undefined.  but not always.  usually on the first
    // pass, never on the second.
});

Я понятия не имею, что происходит, я могу подтвердить, что переменные сеанса установлены правильно, они просто не удерживают свое значение между запросами страниц, но только в первый раз.

Вот как я создаю свой сервер:

app.configure('development', function(){
    app.use(express.cookieParser());
    app.use(express.session({ secret:'yodawgyo' }));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    app.use(express.logger());
    app.use(express.static(__dirname + '/public'));
    app.set('view engine', 'ejs');
    app.set('view options', {
        open: '{{',
        close: '}}'
    });
});

На данный момент у меня только среда dev. У меня есть Node 0.5.0-pre, но эта проблема также появилась на 0.4.1. Я использую express 2.3.2.

Любая помощь очень ценится.

Ответ 1

В сеансе Connect любой обработчик может установить req.session.anything любое значение, а Connect сохранит значение, когда ваш обработчик вызывает end(). Это опасно, если одновременно есть несколько запросов в полете; когда они заканчиваются, одно значение сеанса будет забивать другое. Это является следствием наличия такого простого сеансового API (или прямого доступа к источнику сеанса ), который имеет нет поддержки для атомарного получения и настройки свойств сеанса.

Обходной путь - попытаться предоставить промежуточное ПО сеанса как можно меньше запросов. Вот несколько советов:

  • Поместите ваш обработчик express.static над промежуточным программным обеспечением сеанса.
  • Если вы не можете перемещать некоторые обработчики, которые не нуждаются в сеансе, вы также можете настроить промежуточное программное обеспечение сеанса, чтобы игнорировать любые пути, которые не используют req.session, говоря express.session.ignore.push('/individual/path').
  • Если какой-либо обработчик не записывает на сеанс (возможно, он читает только из сеанса), установите req.session = null; перед вызовом res.end();. Затем он не будет повторно сохранен.

Если только один запрос выполняет чтение-модификацию-запись на сеанс за раз, сбой будет менее вероятным. Надеюсь, что в будущем у Connect будет более точное промежуточное программное обеспечение, но, конечно, API будет более сложным, чем то, что у нас есть.

Ответ 2

Просто боролся с той же проблемой и решил ее решить. Простым ответом является вызов

 Session.save() 

явно, если вы не можете ответить на экспресс-сессию, чтобы вызвать ее для вас в конце ответа.

Ссылка

Ответ 3

Я подал вопрос против Express о github, но выяснил, что было не так через несколько минут. Не уверен, что у вас такая же проблема, но для полноты:

В моем случае я тестировал, перейдя в http://localhost:8003, но поставщик OAuth перенаправлялся на http://hostname: 8003. Тот же блок/сервер/веб-страница, но разные имена доменов означают, что браузер отправляет разные куки файлы, и, следовательно, экспресс получает разные идентификаторы сеанса и данные сеанса. Как только я начал тестировать http://hostname: 8003, все работало нормально.

Ответ 4

Мой код был похож на ваш, структурно. Однако в моем случае моя операция POST возникла из функции JQuery $.post. Я не знаю, имеет ли это заметное различие, однако

Что мне в итоге пришлось сделать, так это отправить ответ "мусор" в конце определения операции POST в моей программе экспресс-маршрутизации, т.е.

res.send("hoo hee ha ha unimportant junk data");

Включив это в конце, я смог вызвать функцию успеха (обратный вызов для попытки отправки AJAX). Я вставил туда перенаправление, вместо того, чтобы поместить его в экспресс-маршруты.

Использовать с AJAX Post window.redirect();

Не использовать с AJAX Post: $res.redirect("someurl");

Это связано с тем, что браузеры, по-видимому, не будут перенаправлять ответ AJAX, поэтому вы должны использовать Javascript, как описано здесь: Экспресс js - не может перенаправлять

Надеюсь, что кто-то помог, он решил проблему для меня, мир.