NodeJS / express: cache e codice di stato 304


92

Quando ricarico un sito web realizzato con express, ottengo una pagina vuota con Safari (non con Chrome) perché il server NodeJS mi invia un codice di stato 304.

Come risolverlo?

Naturalmente, questo potrebbe anche essere solo un problema di Safari, ma in realtà funziona bene su tutti gli altri siti Web, quindi deve essere un problema anche sul mio server NodeJS.

Per generare le pagine, sto usando Jade con res.render.

Aggiornamento: sembra che questo problema si verifichi perché Safari invia 'cache-control': 'max-age=0'in fase di ricarica.

Aggiornamento 2: ora ho una soluzione alternativa, ma esiste una soluzione migliore? Soluzione:

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

Aggiornamento 3: quindi la parte completa del codice è attualmente:

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 non è un problema. Significa semplicemente che la tua risposta non viene modificata e il tuo browser passa alla cache per recuperare la risorsa. Puoi pubblicare il codice pertinente in cui si sta verificando l'anomalia.
Akshat Jiwan Sharma

3
sì, in realtà non è modificato, ma Safari svuota la cache su CMD + R (ricarica) e il server dice solo che non è cambiato.
h345k34cr

In che modo la pagina vuota è correlata al codice di stato 304? Node invierà 304 anche ad altri browser.
user568109

2
È correlato perché con 304 il corpo non viene inviato e il browser utilizza la sua cache, ma poiché non c'è cache, ottieni una pagina vuota
h345k34cr

1
@AkshatJiwanSharma Qualsiasi programma è sviluppato per soddisfare esattamente il contratto del proprietario del prodotto. Il product owner è colui che possiede il codice e paga i soldi, non un'organizzazione che scrive documenti di cui nessuno si preoccupa. Se il contratto dice "200", allora assolutamente qualsiasi stato diverso da "200" è un bug. Quando c'è un bug DEVO riscrivere il codice finché tutto non è esattamente come previsto. Il W3C non ha voce in capitolo.
Gherman,

Risposte:


107

Soluzione più semplice:

app.disable('etag');

Soluzione alternativa qui se desideri un maggiore controllo:

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


2
Potreste spiegare la "soluzione più semplice" o fornire un riferimento su come ciò influisce?
Samuel Méndez

1
@ SamuelMéndez disattiva fondamentalmente la cache, il wiki su etag ha molte buone informazioni en.wikipedia.org/wiki/HTTP_ETag
blented

Ha funzionato per me :)
Naveen Kumar V

3

Come hai detto, Safari invia Cache-Control: max-age=0in ricarica. Express (o più specificamente, la dipendenza di Express, node-fresh) considera la cache non aggiornata quando Cache-Control: no-cachevengono ricevute le intestazioni, ma non fa lo stesso per Cache-Control: max-age=0. Da quello che posso dire, probabilmente dovrebbe. Ma non sono un esperto di memorizzazione nella cache.

La soluzione è cambiare (cosa è attualmente) la riga 37 di node-fresh/index.jsda

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

per

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

I biforcato nodo fresco e esprimo per includere questa correzione nel mio progetto di package.jsonvia npm, si potrebbe fare lo stesso. Ecco le mie forchette, ad esempio:

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

Il ramo safari-reload-fix è basato sul tag 3.4.7.


Ottimo lavoro! Vedo che express 3.5.1 include la tua correzione tramite node-fresh 0.2.2.
Clafou

In realtà, mi sbaglio, la tua correzione è stata ripristinata e in realtà non è arrivata a 0.2.2. Ancora nessuna correzione fresca / rapida.
Clafou

2

Ho avuto lo stesso problema in Safari e Chrome (gli unici che ho testato) ma ho appena fatto qualcosa che sembra funzionare, almeno non sono stato in grado di riprodurre il problema da quando ho aggiunto la soluzione. Quello che ho fatto è stato aggiungere un metatag all'intestazione con un timstamp generato. Non sembra giusto ma è semplice :)

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

Aggiorna PS Per quanto ne so, il problema scompare quando rimuovo il mio proxy del nodo (per proxy intendo sia express.vhost che modulo http-proxy), il che è strano ...


Uso anche un proxy Apache, questo potrebbe essere il problema. La mia soluzione alternativa era disabilitare la memorizzazione nella cache per i siti di contenuto con intestazioni http.
h345k34cr

Disabilitare la cache tramite le intestazioni è sicuramente la strada da percorrere. All'inizio non funzionava per me, ma ora funziona. In altre parole, devo aver commesso un errore da qualche parte la prima volta :)
user907567

1

Prova a utilizzare la navigazione privata in Safari o a eliminare l'intera cache / i cookie.

Ho avuto alcuni problemi simili usando Chrome quando il browser pensava di avere il sito Web nella cache, ma in realtà non lo aveva.

La parte della richiesta http che fa rispondere il server a 304 è l'etag. Sembra che Safari invii l'etichetta corretta senza avere la cache corrispondente.


funziona per me quando ho provato a cancellare l'intera cache, grazie
Yuttanant Suwansiri

0

Vecchia domanda, lo so. La disabilitazione della funzione cache non è necessaria e non è il modo migliore per gestire il problema. Disattivando la funzione cache, il server deve lavorare di più e generare più traffico. Anche il browser e il dispositivo devono lavorare di più, specialmente sui dispositivi mobili questo potrebbe essere un problema.

La pagina vuota può essere facilmente risolta utilizzando il tasto Maiusc + il pulsante di ricarica nel browser.

La pagina vuota può essere il risultato di:

  • un bug nel codice
  • durante il test hai servito una pagina vuota (che non ricordi) che viene memorizzata nella cache dal browser
  • un bug in Safari (in tal caso, segnalalo ad Apple e non provare a risolverlo da solo)

Prova prima il tasto Maiusc della tastiera + il pulsante di ricarica e verifica se il problema persiste e controlla il codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.