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 - не может перенаправлять
Надеюсь, что кто-то помог, он решил проблему для меня, мир.