экспресс-сессия не сохраняется

Я пишу простой сервер для небольшого приложения для Shopify. Получив токен для своего приложения, я хотел сохранить его в сеансе, поэтому использовал express-session. Однако это не сработало.

Я попробовал это решение в приведенном ниже коде.

У ребят из github тоже есть такая проблема:

https://github.com/expressjs/session/issues/371

https://github.com/expressjs/session/issues/633

Вот моя конфигурация:

app.use(session({ 
    secret: 'new app',
    resave: false,
    saveUninitialized: true,
    cookie: {maxAge: 24*60*60*1000}
}))

Это код для получения токена и его сохранения:

request.post(accessTokenRequestUrl, { json: accessTokenPayload })
        .then((accessTokenResponse) => {
            const accessToken = accessTokenResponse.access_token;
            const shopRequestUrl = 'https://' + shop + '/admin/themes.json';
            const shopRequestHeaders = {
                'X-Shopify-Access-Token': accessToken,
            };

            request.get(shopRequestUrl, {headers: shopRequestHeaders})
            .then((shopRes) => {
                let shopObj = JSON.parse(shopRes)
                let themeId = shopObj.themes[0].id;


                req.session.token = accessToken;
                req.session.save();
                console.log(req.session);

                res.json({
                    themeId: themeId,
                    token: accessToken
                })
            })

        })

Мой console.log после этого. Я говорю, что у меня есть токен в объекте сеанса:

Session {
  cookie:
   { path: '/',
     _expires: 2019-02-27T09:01:18.638Z,
     originalMaxAge: 86400000,
     httpOnly: true },
  token: '1354658af88b9417d3c268dd3c22eae4' }

Однако по другому маршруту:

app.get('/shopify/callback/images', (req, res) => {
    console.log(req.session);
    res.send(req.session.token);
})

я получил это

Session {
  cookie:
   { path: '/',
     _expires: 2019-02-27T09:03:56.280Z,
     originalMaxAge: 86400000,
     httpOnly: true } }

Большое спасибо!


person Hung Dang    schedule 26.02.2019    source источник


Ответы (1)


Во-первых, промис всегда должен возвращать промис, если в нем есть какое-либо асинхронное задание.

return request.get(shopRequestUrl, {headers: shopRequestHeaders})

Кроме того, рекомендуется всегда добавлять .catch() в цепочку промисов.

Но реальная проблема здесь в том, что req.session.save() является асинхронным и принимает обратный вызов функция.

req.session.token = accessToken;
req.session.save(() => {
  console.log(req.session);

  return res.json({
    themeId : themeId,
    token   : accessToken,
  });
});
person Martial    schedule 26.02.2019
comment
Да, я исправил это в соответствии с вашими идеями. Я удалил catch() для производства, но это может быть плохой идеей. Я вернул свое обещание и добавил req.session.save((err) => { if (!err) { console.log('token is saved!') } });, но результат не изменился. Кстати, это звучит глупо, но зачем нам обратный вызов для req.session.save()? Это для того, чтобы избежать ошибки? - person Hung Dang; 26.02.2019
comment
Сессия сохраняется автоматически в конце запроса. Если вы хотите, чтобы он был доступен немедленно, вы должны вызвать save(). Но если вы вызовете console.log(req.session) до того, как сессия будет сохранена, вы ничего не получите. - person Martial; 26.02.2019
comment
Спасибо теперь понял! Я думаю, что переключусь на другую базу данных для хранения токена и темы, поскольку сеанс сотрет данные при перезапуске сервера. - person Hung Dang; 27.02.2019