En-têtes pour empêcher les demandes 304 / If-modified-since / HEAD


31

Quels en-têtes dois-je envoyer pour arrêter définitivement toutes les demandes au serveur après la mise en cache du contenu?

Nous avons un serveur à latence très élevée (Sigh, VMWare) donc même l'envoi d'une HEADrequête au serveur prend + 40 ms.

Actuellement, ce sont les en-têtes envoyés / reçus;

Première demande

Le client envoie;

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Pragma: no-cache, no-cache, no-cache
Cache-Control: no-cache, no-cache, no-cache

Le serveur répond;

HTTP/1.1 200 OK
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:51:51 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Last-Modified: Tue, 31 Jan 2012 10:45:11 GMT
Content-Length: 14
Expires: Thu, 31 Jan 2013 14:51:51 GMT
Cache-Control: max-age=31536000

Donc , il envoie un Cache-Controlet Expiresjeu d' en- tête à 365 jours dans l'avenir. Malheureusement, lors du deuxième rafraîchissement, il demande à nouveau l'objet avec un en- If-Modified-Sincetête.

Seconde demande

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
If-Modified-Since: Tue, 31 Jan 2012 10:45:11 GMT
Cache-Control: max-age=0

Réponse;

HTTP/1.1 304 Not Modified
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:58:00 GMT
Vary: Accept-Encoding
Expires: Thu, 31 Jan 2013 14:58:00 GMT
Cache-Control: max-age=31536000

Malheureusement, en raison d'un stupide logiciel de proxy obsolète, nous ne pouvons pas utiliser Keep-Aliveou placer d'autres serveurs / proxys devant l'application. Nous ne pouvons pas non plus améliorer les performances du serveur et réduire la latence du réseau. J'ai essayé de comprendre quels en-têtes nous pouvons envoyer pour se débarrasser des 301 demandes. J'ai essayé d'utiliser ETags mais cela ne fait aucune différence, il envoie toujours un en- If-modified-sincetête. J'ai également essayé de supprimer l'en- Last-Modifiedtête, mais cela provoque simplement une demande GET standard sans mise en cache (vérifié les journaux, le serveur reçoit toujours des demandes).

Les clients sont un mélange de Firefox (principalement), IE 7, 8 et (certains) 9, Chrome et Safari, mais ce comportement semble apparaître dans tous les navigateurs testés.

TL; DR;

Terrible network, quels en-têtes dois-je envoyer pour dire aux clients de ne jamais envoyer de If-modified-sincedemandes au serveur pour valider leur cache et de conserver le contenu en cache jusqu'à ce que l'en- Expirestête soit rencontré?

Il me manque probablement quelque chose d'évident, mais tout ce que j'essaie semble donner les mêmes résultats.

Nous avons un serveur NGINX assis devant notre serveur d'applications afin que je puisse ajouter / supprimer les en-têtes à ma guise. Notre proxy ne prend pas en charge Keep-Alive et le leur n'est aucun moyen d'améliorer les performances du réseau attrayant. En raison de la mauvaise conception du logiciel, l'application Web charge +100 ressources à chaque chargement de page (ouais, le logiciel d'entreprise est nul) avec une latence de ~ 40-50 ms par objet.


1
Hmm, c'est bizarre. L'envoi des en-têtes Expires et âge maximal devrait empêcher de nouvelles demandes d'image. Edit: au fait, quel est le problème avec l'envoi d'un JPG text/plain?
DisgruntledGoat

1
@DisgruntledGoat Ahh, vous avez supposé qu'un fichier .jpg est en fait une image plutôt qu'un document texte. Bienvenue dans mon monde =) (Il s'agit en fait d'un fichier texte qui contient «Hello World» pour mes tests, le logiciel renomme simplement tous les fichiers de manière séquentielle IMG_xxxx.jpg quel que soit le type. Cool hein?)
Smudge

qu'utilisiez-vous pour définir les en-têtes de demande http?
barlop le

Réponses:


25

Vous ne pouvez pas vraiment contrôler les en-têtes que les agents utilisateurs décident de vous envoyer. Si le fichier en question se trouve dans le cache du navigateur et qu'il décide qu'il doit rechercher une nouvelle version, il le fera. Selon cet article , ce sont les situations que les navigateurs demanderont en utilisant If-Modified-Since:

  • L'entrée en cache n'a pas de date d'expiration et le contenu est accédé pour la première fois dans une session de navigateur
  • L'entrée en cache a une date d'expiration mais elle a expiré
  • L'utilisateur a demandé une mise à jour de la page en cliquant sur le bouton Actualiser ou en appuyant sur F5

Donc, si vous rechargez la page pour tester votre mise en cache, cela ne fonctionnera pas car le navigateur demandera à nouveau les images. Essayez de cliquer sur un lien, puis sur un autre lien vers la première page. Si vos utilisateurs rechargent régulièrement des pages, vous devrez peut-être repenser la structure de votre site / application pour éviter cela.

Une chose qui peut aider est d'ajouter "public" à l'en-tête de contrôle du cache, c'est-à-dire Cache-Control: public, max-age=31536000. J'ai également appris récemment qu'une date d'expiration de plus d'un an n'est pas valide. Étant donné que votre date d'expiration est exactement d'un an, une réduction de quelques jours ou semaines pourrait garantir que le fichier reste dans les caches du navigateur et n'est pas supprimé.


Intéressant, je vais réduire les expirations à 60 jours et ajouter le drapeau public et voir ce qui se passe. Cela semblait se produire sur les liens-clics plutôt que sur les F5 (selon Firebug et les journaux du serveur)
Smudge

Techniquement, la spécification HTTP / 1.1 dit seulement que "les serveurs NE DEVRAIENT PAS envoyer de dates d'expiration plus d'un an à l'avenir" (probablement parce que c'est un temps ridiculement long avant l'expiration) et que "environ un an" à l'avenir est l'expiration appropriée il est temps d'envoyer du contenu qui ne devrait jamais expirer.
Ilmari Karonen

1
Après un peu de jeu, j'ai conclu que l'expiration de 365d n'affecte pas nos clients, mais je l'ai laissé tomber pour être sûr, il semble que Cache-Control: public,...c'était la clé de cette situation spécifique.
Smudge

Voulez-vous dire que l'en-tête "public" a corrigé les allers-retours inutiles? Je l'ai essayé, mais sans succès ...
phtrivier

2
Au cas où cela ne serait pas clair dans ma réponse, le rechargement de la page dans votre navigateur demandera à nouveau les fichiers . Cliquez simplement sur les liens pour ouvrir les pages et le navigateur utilise son cache.
DisgruntledGoat


3

J'ai eu le même problème, et les demandes frappent définitivement le serveur pour qu'il réponde avec le 304statut - j'envoie le 304 via du C # et c'est sûr qu'il frappe le serveur ..

J'avais seulement Cache-Control: privatemis. Non max-ageet non ExpiresIl a fonctionné comme prévu; frapper le serveur avec le If-Modified-Sinceoù je teste la valeur par rapport à ce que j'attends et livrer 304avec un corps de réponse vide - sinon 200& remplir le corps de la réponse.

La définition de l'en- Expirestête a eu les résultats souhaités, 200 - (from cache)sur le client et aucune requête HTTP n'a atteint le serveur.

Mais .. J'ai trouvé que le réglage BOTH max-age= & Expirespeut empêcher les navigateurs d'envoyer des en- If-Modified-Sincetêtes ET de ne pas mettre en cache du tout si les valeurs ne correspondent pas .

Quelque chose à savoir si vous avez des problèmes de mise en cache et utilisé les différents en-têtes en combinaison.


1

Un peu hors sujet mais peut-être utile. Une autre amélioration pour vos demandes de contenu mis en cache est de mettre en cache dans sessionStorage afin que vous n'ayez pas besoin de demander au serveur de valider le cache et de recevoir un 304. Regardez par exemple google, ouvrez la console et écrivez sessionStorage. Vous verrez qu'ils mettent en cache CSS ou DOM avec sessionStorage. ofc, vous ne pouvez pas utiliser cela dans les anciens navigateurs IE.


0

Parcourez votre code source et assurez-vous qu'il n'y a pas de META REFRESH pour passer à une autre page. Utilisez plutôt quelque chose comme sendRedirect. Dans ma configuration, META REFRESH produit 304 sous IE, mais pas Chrome. sendRedirect ne produit cela sur aucun navigateur.

<meta http-equiv="refresh" content="0;URL='nextpage'" />    

contre

<% response.sendRedirect("nextpage") %>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.