Экспресс-сессия не сохраняет/не находит сессию

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

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

Как мне заставить его найти уже сохраненный сеанс и вернуть увеличенные значения?

Node.js:

const express = require('express')
const app = express()
const session = require('express-session');

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "http://localhost:5000"); // update to match the domain you will make the request from
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.use(session({
    genid: function(req) {
        return 1
    },
    proxy: true,
    secret: "max",
    resave: false,
    saveUninitialized: true
}));

app.get('/', function (req, res) {
    console.log(req.session)
    if (!req.session.views) {
        req.session.views=0;
    }
    res.send((req.session.views++).toString());
    console.log(req.session)
})

app.listen(3000)

Базовая стройность:

<script>
    export let name;
    let resp = "";
    async function sendReq() {
        resp = await fetch("http://localhost:3000/");
        console.log(resp);
        resp = await resp.text();
        console.log(resp);
    }
</script>

<main>
    <h1>Hello {name}!</h1>
    <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
    <button on:click={sendReq}>Click me</button>
    {resp}
</main>

<style>
    main {
        text-align: center;
        padding: 1em;
        max-width: 240px;
        margin: 0 auto;
    }

    h1 {
        color: #ff3e00;
        text-transform: uppercase;
        font-size: 4em;
        font-weight: 100;
    }

    @media (min-width: 640px) {
        main {
            max-width: none;
        }
    }
</style>

person yodigi7    schedule 13.12.2019    source источник
comment
После изменения объекта сеанса вы должны выполнить session.save(). Кроме того, почему вы жестко кодируете genId(), чтобы каждый раз возвращать один и тот же идентификатор? Если у вас нет особой причины для самостоятельного создания идентификатора сеанса, удалите этот метод и дайте поведение по умолчанию работать на вас.   -  person jfriend00    schedule 13.12.2019


Ответы (1)


fetch() по умолчанию не отправляет куки со своим запросом. Таким образом, без файлов cookie ваш сервер не увидит файл cookie сеанса, а затем не найдет ваш предыдущий объект сеанса. Вам нужно добавить опцию credentials: "include" или credentials: "same-origin":

resp = await fetch("http://localhost:3000/", {credentials: "include"});

Вам также может понадобиться вызвать session.save() после изменения объекта сеанса, чтобы ваше изменение сохранялось.

Некоторые другие комментарии к вашему коду:

  1. Для большинства сеансов с реальным хранилищем данных вам необходимо вызвать session.save() после изменения объекта сеанса, чтобы убедиться, что он сохранен обратно в хранилище данных. Вам, вероятно, это не нужно для хранилища в памяти по умолчанию, но это хорошая общая практика, поскольку рабочий код, вероятно, в какой-то момент переместится из хранилища в памяти.

  2. Если вы жестко запрограммируете genid(), чтобы всегда возвращать 1, это сломает кучу функций в сеансах. Не делай этого. Реализация genid() по умолчанию отлично подойдет для ваших целей, поэтому вы можете просто полностью удалить определение этого метода.

  3. Вы не показываете код для загрузки вашей веб-страницы с вашего сервера. Если вы не получаете саму веб-страницу со своего веб-сервера, поэтому вызов fetch() является вызовом того же происхождения, то у вас также могут быть проблемы с cors (ограничения между источниками).

  4. В вашем клиентском коде вы должны переместить определение переменной resp внутрь вашей функции sendReq(), чтобы она была локальной переменной и не прерывалась, если одна и та же страница выполняла более одного вызова sendReq().

person jfriend00    schedule 13.12.2019
comment
Да, это просто игровая площадка, чтобы возиться и изучать экспресс-сессии, просто пытаясь заставить это работать в данный момент. Когда я устанавливаю credentials: "same-origin", это ничего не меняет. Однако при установке credentials: "include". Я получаю сообщение об ошибке: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. - person yodigi7; 13.12.2019
comment
Кроме того, почтальон по умолчанию не сохраняет и не отправляет файлы cookie, или его просто проще протестировать в базовом приложении svelte. - person yodigi7; 13.12.2019
comment
Только что нашел проблему, похоже, вам нужно вызывать session.save() даже с хранилищем в памяти. Если вы хотите отредактировать свой ответ, я могу отметить его как правильный. Кроме того, для заголовка Allow-Credentials добавлено значение true. - person yodigi7; 13.12.2019
comment
@ yodigi7 - я не знал, что это запрос о перекрестном происхождении. Рад, что ты разобрался. - person jfriend00; 14.12.2019