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

92

Lorsque je recharge un site Web réalisé avec express, j'obtiens une page vierge avec Safari (pas avec Chrome) car le serveur NodeJS m'envoie un code de statut 304.

Comment résoudre ça?

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

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

Mise à jour: il semble que ce problème se produit car Safari envoie 'cache-control': 'max-age=0'lors du rechargement.

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

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: La partie du code complet est donc 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);
    }
}
h345k34cr
la source
1
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 publier le code pertinent dans lequel l'anomalie se produit.
Akshat Jiwan Sharma
3
oui, en fait il n'est pas modifié, mais Safari vide son cache sur CMD + R (recharger) et le serveur dit seulement qu'il n'a pas changé.
h345k34cr
Comment la page vierge est-elle liée au code d'état 304? Node enverrait également 304 à d'autres navigateurs.
user568109
2
C'est lié parce qu'avec 304 le corps n'est pas envoyé et le navigateur utilise son cache, mais comme il n'y a pas de cache, vous obtenez une page vierge
h345k34cr
1
@AkshatJiwanSharma Tout programme est développé pour répondre exactement au contrat du propriétaire du produit. Le propriétaire du produit est celui qui possède le code et qui paie l'argent, pas une organisation qui rédige des articles dont personne ne se soucie. Si le contrat dit «200», alors absolument tout statut qui n'est pas égal à «200» est un bogue. Quand il y a un bug, je DOIS réécrire le code jusqu'à ce que tout soit exactement comme prévu. Le W3C n'a pas son mot à dire en la matière.
Gherman

Réponses:

107

Solution la plus simple:

app.disable('etag');

Solution alternative 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/

blenté
la source
2
Pourriez-vous expliquer la «solution la plus simple» ou donner une référence sur la façon dont cela affecte?
Samuel Méndez
1
@ SamuelMéndez cela désactive la mise en cache en gros, le wiki sur etag a beaucoup de bonnes informations en.wikipedia.org/wiki/HTTP_ETag
blented
A travaillé pour moi :)
Naveen Kumar V
3

Comme vous l'avez dit, Safari envoie Cache-Control: max-age=0lors du rechargement. Express (ou plus spécifiquement, la dépendance d'Express, node-fresh) considère le cache obsolète lorsque les en- Cache-Control: no-cachetêtes sont reçus, mais il ne fait pas la même chose pourCache-Control: max-age=0 . D'après ce que je peux dire, cela devrait probablement. Mais je ne suis pas un expert de la mise en cache.

La solution est de changer la ligne (ce qui est actuellement) 37 node-fresh/index.jsde

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 forké node-fresh et express pour inclure ce correctif dans mon projet package.jsonvianpm , vous pouvez 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.

James P. Javery
la source
Bon travail! Je vois qu'express 3.5.1 inclut votre correctif via node-fresh 0.2.2.
Clafou
En fait, je me trompe, votre correctif a été rétabli et n'a pas atteint la version 0.2.2. Toujours pas de solution fraîche / express.
Clafou
2

J'ai eu 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 été en mesure de reproduire le problème depuis que j'ai ajouté la solution. Ce que j'ai fait, c'est ajouter une balise meta à l'en-tête avec un horodatage généré. Ça ne semble pas juste mais c'est simple :)

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

Mise à jour PS Autant que je sache, le problème disparaît lorsque je supprime mon proxy de nœud (par proxy, j'entends à la fois le module express.vhost et http-proxy), ce qui est bizarre ...

user907567
la source
J'utilise également un proxy Apache, cela pourrait être le problème. Ma solution de contournement consistait simplement à désactiver la mise en cache pour les sites de contenu avec des en-têtes http.
h345k34cr
La désactivation du cache via les en-têtes est certainement la voie à suivre. Au début, cela ne fonctionnait pas pour moi, mais maintenant c'est le cas. En d'autres termes, j'ai dû faire une erreur quelque part la première fois :)
user907567
1

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 lors de l'utilisation de chrome lorsque le navigateur pensait qu'il avait le site Web dans son cache, mais qu'il ne l'avait pas fait.

La partie de la requête http qui oblige le serveur à répondre à 304 est l'etag. On dirait que Safari envoie le bon etag sans avoir le cache correspondant.

sbugert
la source
cela fonctionne pour moi quand j'ai essayé de supprimer tout le cache, merci
Yuttanant Suwansiri
0

Vieille question, je sais. La désactivation de la fonction de cache n'est pas nécessaire et n'est pas la meilleure façon de gérer le problème. En désactivant la fonction de cache, le serveur doit travailler plus dur et générer plus de trafic. De plus, le navigateur et l'appareil doivent travailler plus dur, en particulier sur les appareils mobiles, cela pourrait être un problème.

La page vide peut être facilement résolue en utilisant la touche Maj + le bouton de rechargement dans le navigateur.

La page vide peut être le résultat de:

  • un bug dans votre code
  • pendant le test, vous avez servi une page vide (dont vous ne vous souvenez pas) qui est mise en cache par le navigateur
  • un bogue dans Safari (si c'est le cas, veuillez le signaler à Apple et n'essayez pas de le réparer vous-même)

Essayez d'abord la touche du clavier Shift + le bouton de rechargement et voyez si le problème persiste et vérifiez votre code.

Codebeat
la source