NodeJS / express: Cache e código de status 304


92

Quando recarrego um site feito com express, recebo uma página em branco com Safari (não com Chrome) porque o servidor NodeJS me envia um código de status 304.

Como resolver isso?

Claro, isso também pode ser apenas um problema do Safari, mas na verdade ele funciona bem em todos os outros sites, então deve ser um problema no meu servidor NodeJS também.

Para gerar as páginas, estou usando Jade com res.render.

Atualização: parece que esse problema ocorre porque o Safari envia 'cache-control': 'max-age=0'na recarga.

Atualização 2: agora tenho uma solução alternativa, mas existe uma solução melhor? Gambiarra:

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…
}

Atualização 3: Portanto, a parte completa do código é atualmente:

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);
    }
}

1
304 não é um problema. Significa simplesmente que sua resposta não é modificada e seu navegador usa o cache para buscar o recurso. Você pode postar o código relevante em que a anomalia está acontecendo.
Akshat Jiwan Sharma

3
sim, na verdade ele não foi modificado, mas o Safari esvazia seu cache no CMD + R (recarregar) e o servidor apenas diz que não mudou.
h345k34cr

Como a página em branco está relacionada ao código de status 304? O Node também enviaria 304 para outros navegadores.
user568109

2
Está relacionado porque com 304 o corpo não é enviado e o navegador usa seu cache, mas como não há cache, você obtém uma página em branco
h345k34cr

1
@AkshatJiwanSharma Qualquer programa é desenvolvido para atender exatamente ao contrato do proprietário do produto. O product owner é aquele que possui o código e paga o dinheiro, não uma organização que escreve artigos com os quais ninguém se importa. Se o contrato disser "200", então absolutamente qualquer status que não seja igual a "200" é um bug. Quando há um bug, devo reescrever o código até que tudo esteja exatamente como o esperado. O W3C não tem uma palavra a dizer sobre o assunto.
Gherman

Respostas:


110

Solução mais fácil:

app.disable('etag');

Solução alternativa aqui se você quiser mais controle:

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


3
Você poderia explicar a "solução mais fácil" ou dar uma referência sobre como isso afeta?
Samuel Méndez

2
@ SamuelMéndez ele desativa o cache basicamente, o wiki em etag tem muitas informações boas en.wikipedia.org/wiki/HTTP_ETag
blented

Trabalhou para mim :)
Naveen Kumar V

Isso faz sentido. Eu acredito que a etag não estava sendo recomputada corretamente porque eu não estava definindo a data da última modificação, conforme mencionado no link de vlasenko. Meu problema foi embora quando atualizei meu código da seguinte maneira: const headers = {'Last-Modified': (new Date ()). ToUTCString ()}; app.get ('/ *', (req, res) => {res.sendFile (join (DIST_FOLDER + '/index.html'), {headers});});
Robert Patterson

3

Como você disse, o Safari envia Cache-Control: max-age=0na hora de recarregar. Express (ou mais especificamente, a dependência de Express, node-fresh) considera o cache obsoleto quando os Cache-Control: no-cachecabeçalhos são recebidos, mas não faz o mesmo para Cache-Control: max-age=0. Pelo que posso dizer, provavelmente deveria. Mas não sou um especialista em cache.

A correção é a mudança (que é atualmente) linha 37 de node-fresh/index.jsde

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

para

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

Eu fiz um fork do node-fresh and express para incluir essa correção no meu projeto package.jsonvia npm, você poderia fazer o mesmo. Aqui estão meus garfos, por exemplo:

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

O branch safari-reload-fix é baseado na tag 3.4.7.


Ótimo trabalho! Vejo que o Express 3.5.1 inclui sua correção via node-fresh 0.2.2.
Clafou de

Na verdade, estou errado, sua correção foi revertida e não chegou a 0.2.2. Ainda sem correção fresca / expressa.
Clafou

2

Tente usar a navegação privada no Safari ou deletar todo o seu cache / cookies.

Tive alguns problemas semelhantes ao usar o Chrome quando o navegador pensou que tinha o site em seu cache, mas na verdade não tinha.

A parte da solicitação http que faz o servidor responder 304 é o etag. Parece que o Safari está enviando a etag correta sem ter o cache correspondente.



2

Tive o mesmo problema no Safari e no Chrome (os únicos que testei), mas acabei de fazer algo que parece funcionar, pelo menos não consegui reproduzir o problema desde que adicionei a solução. O que fiz foi adicionar uma metatag ao cabeçalho com um carimbo de data / hora gerado. Não parece certo, mas é simples :)

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

Update PS Pelo que eu posso dizer, o problema desaparece quando eu removo meu proxy de nó (por proxy, quero dizer ambos express.vhost e módulo http-proxy), o que é estranho ...


Eu também uso um proxy Apache, esse pode ser o problema. Minha solução alternativa foi apenas desativar o cache de sites de conteúdo com cabeçalhos http.
h345k34cr

Desativar o cache por meio dos cabeçalhos é definitivamente o caminho a percorrer. No começo não funcionou para mim, mas agora funciona. Em outras palavras, devo ter cometido um erro em algum lugar da primeira vez :)
user907567

0

Velha pergunta, eu sei. Desativar o recurso de cache não é necessário e não é a melhor maneira de gerenciar o problema. Ao desabilitar o recurso de cache, o servidor precisa trabalhar mais e gerar mais tráfego. Além disso, o navegador e o dispositivo precisam trabalhar mais, especialmente em dispositivos móveis, isso pode ser um problema.

A página vazia pode ser facilmente resolvida usando a tecla Shift + botão recarregar no navegador.

A página vazia pode ser o resultado de:

  • um bug em seu código
  • durante o teste, você veiculou uma página vazia (você não lembra) que é armazenada em cache pelo navegador
  • um bug no Safari (em caso afirmativo, informe à Apple e não tente corrigi-lo sozinho)

Experimente primeiro a tecla Shift do teclado + botão recarregar e veja se o problema ainda existe e reveja o seu código.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.