NodeJS / express: кеш и код состояния 304

92

Когда я перезагружаю веб-сайт, созданный с помощью express, я получаю пустую страницу с Safari (не с Chrome), потому что сервер NodeJS отправляет мне код состояния 304.

Как это решить?

Конечно, это также может быть проблемой Safari, но на самом деле он отлично работает на всех других веб-сайтах, так что это должно быть проблемой и на моем сервере NodeJS.

Для создания страниц я использую Jade с расширением res.render.

Обновление: похоже, что эта проблема возникает из-за того, что Safari отправляет 'cache-control': 'max-age=0'при перезагрузке.

Обновление 2: теперь у меня есть обходной путь, но есть ли лучшее решение? Обходной путь:

app.get('/:language(' + content.languageSelector + ')/:page', function (req, res)
{
    // Disable caching for content files
    res.header("Cache-Control", "no-cache, no-store, must-revalidate");
    res.header("Pragma", "no-cache");
    res.header("Expires", 0);

    // rendering stuff here…
}

Обновление 3: Итак, полная часть кода в настоящее время:

app.get('/:language(' + content.languageSelector + ')/:page', pageHandle);

function pageHandle (req, res)
{
    var language = req.params.language;
    var thisPage = content.getPage(req.params.page, language);

    if (thisPage)
    {
        // Disable caching for content files
        res.header("Cache-Control", "no-cache, no-store, must-revalidate");
        res.header("Pragma", "no-cache");
        res.header("Expires", 0);

        res.render(thisPage.file + '_' + language, {
            thisPage : thisPage,
            language: language,
            languages: content.languages,
            navigation: content.navigation,
            footerNavigation: content.footerNavigation,
            currentYear: new Date().getFullYear()
        });
    }
    else
    {
        error404Handling(req, res);
    }
}
h345k34cr
источник
1
304 не проблема. Это просто означает, что ваш ответ не изменяется, и ваш браузер переключается в кеш для извлечения ресурса. Можете выложить соответствующий код, в котором происходит аномалия.
Акшат Дживан Шарма
3
да, на самом деле он не изменен, но Safari очищает свой кеш на CMD + R (перезагрузка), и сервер только говорит, что он не изменился.
h345k34cr
Как пустая страница связана с кодом статуса 304? Node также отправит 304 другим браузерам.
user568109
2
Это связано с тем, что с 304 тело не отправляется, и браузер использует свой кеш, но поскольку кеша нет, вы получаете пустую страницу
h345k34cr
1
@AkshatJiwanSharma Любая программа разрабатывается в точном соответствии с условиями контракта с владельцем продукта. Владелец продукта - это тот, кто владеет кодом и платит деньги, а не какая-то организация, которая пишет статьи, которые никого не интересуют. Если в контракте указано «200», то абсолютно любой статус, отличный от «200», является ошибкой. Когда есть ошибка, я ДОЛЖЕН переписать код, пока все не станет именно таким, как ожидалось. W3C не имеет права голоса по этому поводу.
Gherman

Ответы:

107

Самое простое решение:

app.disable('etag');

Альтернативное решение здесь, если вам нужен больший контроль:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/

смешанный
источник
2
Не могли бы вы объяснить «самое простое решение» или дать ссылку на то, как это повлияет?
Samuel Méndez
1
@ SamuelMéndez он в основном отключает кеширование, в вики на etag есть много полезной информации en.wikipedia.org/wiki/HTTP_ETag
смешано
Сработало для меня :)
Naveen Kumar V
3

Как вы сказали, Safari отправляет Cache-Control: max-age=0на перезагрузку. Express (или, точнее, зависимость Express, node-fresh) считает кеш устаревшим при получении Cache-Control: no-cacheзаголовков, но не делает того же для Cache-Control: max-age=0. Насколько я могу судить, вероятно, должно. Но я не специалист по кешированию.

Исправление состоит в том, чтобы изменить (текущую) строку 37 node-fresh/index.jsиз

if (cc && cc.indexOf('no-cache') !== -1) return false;  

к

if (cc && (cc.indexOf('no-cache') !== -1 ||
  cc.indexOf('max-age=0') !== -1)) return false;

Я раздвоенный узел свежий и выразить включить это исправление в моем проект - й с package.jsonпомощью npm, вы могли бы сделать то же самое. Вот мои вилки, например:

https://github.com/stratusdata/node-fresh https://github.com/stratusdata/express#safari-reload-fix

Ветка safari-reload-fix основана на теге 3.4.7.

Джеймс П. Джавери
источник
Отличная работа! Я вижу, что express 3.5.1 включает ваше исправление через node-fresh 0.2.2.
Clafou
На самом деле, я ошибаюсь, ваше исправление было отменено и на самом деле не дошло до версии 0.2.2. Все еще нет свежего / экспресс-исправления.
Clafou
2

У меня была такая же проблема в Safari и Chrome (единственных из них, которые я тестировал), но я просто сделал что-то, что, кажется, работает, по крайней мере, я не смог воспроизвести проблему с тех пор, как добавил решение. Я добавил в заголовок метатег с сгенерированной временной меткой. Не кажется правильным, но все просто :)

<meta name="304workaround" content="2013-10-24 21:17:23">

Обновление PS Насколько я могу судить, проблема исчезает, когда я удаляю прокси-сервер узла (под прокси я подразумеваю как модуль express.vhost, так и модуль http-proxy), что странно ...

user907567
источник
Я также использую прокси Apache, это может быть проблемой. Мое обходное решение состояло в том, чтобы просто отключить кеширование для сайтов с контентом с заголовками http.
h345k34cr
Отключение кеша через заголовки - определенно правильный путь. Сначала у меня это не сработало, но теперь работает. Другими словами, я должен был где-то ошибиться в первый раз :)
user907567
1

Попробуйте использовать приватный просмотр в Safari или удалить весь кеш / файлы cookie.

У меня были похожие проблемы с использованием Chrome, когда браузер думал, что у него есть веб-сайт в кеше, но на самом деле этого не было.

Часть http-запроса, которая заставляет сервер отвечать 304, является etag. Похоже, Safari отправляет правильный etag, не имея соответствующего кеша.

sbugert
источник
это
сработало
0

Старый вопрос, я знаю. Отключение функции кеширования не требуется и не лучший способ решить проблему. Отключив кэширование, сервер должен работать больше и генерировать больше трафика. Кроме того, браузеру и устройству нужно работать усерднее, особенно на мобильных устройствах это может быть проблемой.

Пустая страница может быть легко решена с помощью клавиши Shift + кнопки перезагрузки в браузере.

Пустая страница может быть результатом:

  • ошибка в вашем коде
  • во время тестирования вы обслуживали пустую страницу (вы не можете вспомнить), которая кешируется браузером
  • ошибка в Safari (если да, сообщите об этом в Apple и не пытайтесь исправить самостоятельно)

Попробуйте сначала нажать клавишу Shift + кнопку перезагрузки и посмотреть, сохраняется ли проблема, и просмотрите свой код.

Codebeat
источник