126 votes

NodeJS/express : Cache et code d'état 304

Lorsque je recharge un site web réalisé avec express, j'obtiens une page blanche avec Safari (pas avec Chrome) car le serveur NodeJS m'envoie un code d'état 304.

Comment résoudre ce problème ?

Bien sûr, cela pourrait aussi être un problème de Safari, mais en fait, cela fonctionne bien sur tous les autres sites web, donc cela doit être un problème sur mon serveur NodeJS, aussi.

Pour générer les pages, j'utilise Jade avec res.render .

Mise à jour : Il semble que ce problème survienne parce que Safari envoie 'cache-control': 'max-age=0' lors du rechargement.

Mise à jour 2 : J'ai maintenant une solution de contournement, mais existe-t-il une meilleure solution ? Solution de rechange :

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

Mise à jour 3 : Donc la partie complète du code est actuellement :

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

4 votes

La 304 n'est pas un problème. Cela signifie simplement que votre réponse n'est pas modifiée et que votre navigateur se tourne vers le cache pour récupérer la ressource. Pouvez-vous poster le code pertinent dans lequel l'anomalie se produit.

3 votes

Oui, en fait il n'est pas modifié, mais Safari vide son cache sur CMD + R (reload) et le serveur dit seulement qu'il n'a pas changé.

0 votes

Comment la page blanche est-elle liée au code d'état 304 ? Node enverrait également 304 à d'autres navigateurs.

142voto

blented Points 187

La solution la plus simple :

app.disable('etag');

Une autre solution ici si vous voulez plus de contrôle :

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

7 votes

Pourriez-vous expliquer la "solution la plus simple" ou donner une référence sur la façon dont cela affecte ?

2 votes

@SamuelMéndez il désactive le cache en gros, le wiki sur etag a beaucoup de bonnes infos fr.wikipedia.org/wiki/HTTP_ETag

0 votes

Ça a marché pour moi :)

5voto

sbugert Points 116

Essayez d'utiliser la navigation privée dans Safari ou de supprimer l'intégralité de votre cache/cookies.

J'ai eu des problèmes similaires en utilisant chrome lorsque le navigateur pensait avoir le site web dans son cache mais en fait non.

La partie de la requête http qui fait que le serveur répond un 304 est le etag. Il semble que Safari envoie le bon etag sans avoir le cache correspondant.

0 votes

Ça marche pour moi quand j'ai essayé de supprimer tout le cache, merci.

3voto

James P. Javery Points 11

Comme vous l'avez dit, Safari envoie Cache-Control: max-age=0 lors du rechargement. Express (ou plus précisément, la dépendance d'Express, node-fresh) considère que le cache est périmé lorsque Cache-Control: no-cache sont reçus, mais il n'en va pas de même pour les éléments suivants Cache-Control: max-age=0 . D'après ce que je peux dire, il devrait probablement le faire. Mais je ne suis pas un expert de la mise en cache.

Le correctif consiste à modifier (ce qui est actuellement) la ligne 37 du document node-fresh/index.js de

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

à

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

J'ai bifurqué sur node-fresh et express pour inclure ce correctif dans mon projet package.json via npm vous pourriez faire de même. Voici mes fourches, par exemple :

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

La branche safari-reload-fix est basée sur la balise 3.4.7.

0 votes

Excellent travail ! Je vois que express 3.5.1 inclut votre correction via node-fresh 0.2.2.

0 votes

En fait, je me trompe, votre correction a été annulée et n'a pas été intégrée à la version 0.2.2. Il n'y a toujours pas de correctif nouveau/express.

3voto

user907567 Points 11

J'avais le même problème dans Safari et Chrome (les seuls que j'ai testés) mais je viens de faire quelque chose qui semble fonctionner, du moins je n'ai pas pu reproduire le problème depuis que j'ai ajouté la solution. Ce que j'ai fait, c'est ajouter une métabalise à l'en-tête avec un horodatage généré. Cela ne semble pas correct mais c'est simple :)

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

Update P.S Pour autant que je puisse dire, le problème disparaît lorsque je supprime mon proxy de nœud (par proxy j'entends à la fois express.vhost et le module http-proxy), ce qui est bizarre...

0 votes

J'utilise également un proxy Apache, cela pourrait être le problème. Ma solution de contournement a été de désactiver la mise en cache pour les sites de contenu avec des en-têtes http.

0 votes

La désactivation du cache par le biais des en-têtes est certainement la meilleure solution. Au début, ça ne marchait pas pour moi, mais maintenant ça marche. En d'autres termes, j'ai dû faire une erreur quelque part la première fois :)

1voto

Dakuan Points 717

Nous avons créé ceci pour aider à le contourner :

https://github.com/Dakuan/jumanji

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X