web-dev-qa-db-fra.com

"Cache-Control: max-age = 0, no-cache" mais le navigateur contourne la requête du serveur (et cache le cache)?

J'utilise Chrome 40 (quelque chose de gentil et de moderne).

Cache-Control: max-age=0, no-cache est défini sur toutes les pages - je m'attends donc à ce que le navigateur utilise quelque chose de son cache s'il a d'abord vérifié auprès du serveur et obtenu une réponse 304 Not Modified.

Cependant, en appuyant sur le bouton Précédent, le navigateur frappe joyeusement son propre cache sans vérifier avec le serveur.

Si j'ouvre la même page, comme je l'ai atteint avec le bouton Précédent, dans un nouvel onglet, il vérifie auprès du serveur (et obtient une réponse 303 See Other lorsque les choses ont changé).

Voir les captures d'écran ci-dessous illustrant la sortie des deux cas différents à partir de l'onglet Réseau des outils de développement Chrome.

J'ai pensé que je pourrais utiliser max-age=0, no-cache comme alternative plus légère à no-store, où je ne veux pas que les utilisateurs voient des données périmées via le bouton Précédent (mais où les données ne sont pas précieuses et peuvent donc être mises en cache).

Ma compréhension de no-cache (voir ici et ici sur SO) est que le navigateur doit toujours revalider toutes les réponses. Alors, pourquoi Chrome ne le fait-il pas lorsque vous utilisez le bouton Précédent?

no-store est-il la seule option?


200 réponse (du cache) en appuyant sur le bouton Précédent:

enter image description here

303 réponse à la demande de la même page dans un nouvel onglet:

enter image description here

13
George Hawkins

De http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1

no-cache

Si la directive no-cache ne spécifie pas de nom de champ, un cache NE DOIT PAS utiliser la réponse pour satisfaire une demande ultérieure sans revalidation réussie avec le serveur Origin. Cela permet à un serveur Origin d'empêcher la mise en cache même par des caches configurés pour renvoyer des réponses obsolètes aux demandes des clients. 

Si la directive no-cache spécifie un ou plusieurs noms de champs, un cache PEUT utiliser la réponse pour satisfaire une demande ultérieure, sous réserve de toute autre restriction relative à la mise en cache. Cependant, le nom de champ spécifié NE DOIT PAS être envoyé dans la réponse à une demande ultérieure sans revalidation réussie avec le serveur d'origine. Cela permet à un serveur Origin d'empêcher la réutilisation de certains champs d'en-tête dans une réponse, tout en permettant la mise en cache du reste de la réponse.

no-cache n'exige pas que la réponse ne soit pas stockée dans le cache. Il spécifie simplement que la réponse mise en cache ne doit pas être réutilisée pour servir une demande later sans la revalider, il s'agit donc d'un raccourci pour must-revalidate, max-age=0.

Il appartient au navigateur de qualifier une demande ultérieure et, à ma connaissance, l’utilisation du bouton Précédent ne le permet pas. Ce comportement varie selon les moteurs de navigateur.

no-store interdit l'utilisation de la réponse en cache pour toutes les demandes, pas seulement pour les suivantes.

Notez que même avec no-store, la RFC autorise en réalité le client à stocker la réponse pour une utilisation dans les tampons d'historique. Cela signifie que le client peut toujours utiliser une réponse mise en cache, même si no-store a été spécifié.

Le dernier comportement couvre les cas où la page a été enregistrée avec son titre de page d'origine dans l'historique du navigateur. Un autre cas d'utilisation concerne le comportement de divers navigateurs mobiles qui ne supprimeront pas la page précédente tant que la page suivante ne sera pas complètement chargée, l'utilisateur pouvant éventuellement abandonner.

Pour clarifier le comportement du bouton Précédent: Il n’est soumis à aucun en-tête de cache, selon http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.13

Les agents utilisateurs disposent souvent de mécanismes d'historique, tels que des boutons "Précédent" et des listes d'historique, qui peuvent être utilisés pour afficher à nouveau une entité extraite précédemment dans une session.

Les mécanismes de l'histoire et les caches sont différents. En particulier, les mécanismes d'historique NE DEVRAIENT PAS essayer de montrer une vue sémantiquement transparente de l'état actuel d'une ressource. Un mécanisme d’historique vise plutôt à montrer exactement ce que l’utilisateur a vu au moment où la ressource a été extraite.

Par défaut, une heure d'expiration ne s'applique pas aux mécanismes de l'historique. Si l'entité est toujours en mémoire, un mécanisme d'historique DEVRAIT l'afficher même si l'entité est arrivée à expiration, sauf si l'utilisateur a spécifiquement configuré l'agent pour actualiser les documents d'historique ayant expiré.

Cela signifie que le comportement recommandé est le non-respect des en-têtes de contrôle du cache lors de l'utilisation du bouton Précédent. Si votre navigateur respecte une date d'expiration antidatée ou applique la directive no-store non seulement au cache du navigateur, mais également à l'historique, il s'éloigne déjà de cette recommandation.

Pour le résoudre:
Vous ne pouvez pas et vous n'êtes pas censé le faire. Si l'utilisateur revient à une page précédemment visitée, la plupart des navigateurs tenteront même de restaurer la fenêtre d'affichage. Vous pouvez utiliser un mécanisme différé tel que AJAX pour actualiser le contenu s'il s'agissait du comportement d'origine avant que l'utilisateur ne quitte la page. Sinon, vous ne devriez même pas modifier le contenu.

23
Ext3h

Avez-vous essayé d'utiliser le vieil ensemble complet d'en-têtes sans cache?

<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />

Cela semble fonctionner tout le temps, sauf si vous utilisez un site Web "pushState".

1
Ingmars

On dirait que c'est une «bizarrerie» connue dans Chrome avec l'utilisation du bouton de retour. Il y a une bonne discussion de la question dans le rapport de bogue pour cela ici:

https://code.google.com/p/chromium/issues/detail?id=28035

Malheureusement, il semblerait que la plupart des gens se soient tournés vers le non-magasin.

J'espère cependant que la plupart des utilisateurs sont habitués à ne pas obtenir d'actualisation complète de la page à l'aide du bouton de retour. Si vous pensez à la plupart des applications Angular ou Backbone qui gèrent elles-mêmes l'action de retour afin que vous actualisiez simplement le contenu et non la page. Gardant cela à l’esprit, je soupçonne que le fait d’actualiser le client ou d’obtenir des mises à jour à son retour n’est pas si inattendu.

1
JodiMiddleton