web-dev-qa-db-fra.com

Prévention de la mise en cache iframe dans le navigateur

Comment empêchez-vous Firefox et Safari de mettre en cache du contenu iframe?

J'ai une page Web simple avec un iframe à une page sur un site différent. La page externe et la page interne ont des en-têtes de réponse HTTP pour empêcher la mise en cache. Lorsque je clique sur le bouton "Précédent" du navigateur, la page externe fonctionne correctement, mais quoi qu'il en soit, le navigateur récupère toujours un cache de la page iframed. IE fonctionne très bien, mais Firefox et Safari me posent problème.

Ma page Web ressemble à ceci:

<html>
  <head><!-- stuff --></head>
<body>
  <!-- stuff -->
  <iframe src="webpage2.html?var=xxx" />
  <!-- stuff -->
</body>
</html>

La variable var change toujours. Malgré le fait que l'URL de l'iframe a changé (et donc, le navigateur devrait effectuer une nouvelle requête sur cette page), il récupère simplement le contenu mis en cache.

J'ai examiné les requêtes et les réponses HTTP, et j'ai remarqué que même si la page extérieure contenait <iframe src="webpage2.html?var=222" />, le navigateur irait toujours chercher webpage2.html?var=111.

Voici ce que j'ai essayé jusqu'à présent:

  • Modification de l'URL d'iframe avec une valeur var aléatoire
  • Ajout d'en-têtes Expires, Cache-Control et Pragma à la page Web externe
  • Ajout d'en-têtes Expires, Cache-Control et Pragma à la page Web interne

Je ne peux pas faire d'astuces JavaScript car je suis bloqué par la règle de même origine. 

Je manque d'idées. Est-ce que quelqu'un sait comment empêcher le navigateur de mettre en cache le contenu iframed?

Mettre à jour

J'ai installé Fiddler2 comme Daniel l'avait suggéré d'effectuer un autre test et, malheureusement, j'obtiens toujours les mêmes résultats.

C'est le test que j'ai effectué:

  1. La page extérieure génère un nombre aléatoire à l'aide de Math.random() dans JSP.
  2. La page extérieure affiche un nombre aléatoire sur la page Web.
  3. La page extérieure appelle iframe, en passant un nombre aléatoire.
  4. La page intérieure affiche un nombre aléatoire.

Avec ce test, je peux voir exactement quelles pages sont mises à jour et quelles pages sont mises en cache.

Test visuel

Pour un test rapide, je charge la page, navigue vers une autre page, puis appuie sur "retour". Voici les résultats:

Page d'origine:

  • Page extérieure: 0.21300034290246206
  • Page intérieure: 0.21300034290246206

Quitter la page, puis revenir en arrière:

  • Page extérieure: 0.447092901919483644
  • Page intérieure: 0.21300034290246206

Cela montre que la page interne est mise en cache, même si la page externe l'appelle avec un paramètre GET différent dans l'URL. Pour une raison quelconque, le navigateur ignore le fait que l’iframe demande une nouvelle URL; il charge simplement l'ancien.

Test de violoneux

Effectivement, Fiddler confirme la même chose.

(Je charge la page.)

La page extérieure est appelée. HTML:

0.21300034290246206
<iframe src="http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206" />

http: //ipv4.fiddler: 1416/page1.aspx? var = 0.21300034290246206 est appelé.

(Je navigue en dehors de la page, puis je reviens.)

La page extérieure est appelée. HTML:

0.4470929019483644
<iframe src="http://ipv4.fiddler:1416/page1.aspx?var=0.4470929019483644" />

http: //ipv4.fiddler: 1416/page1.aspx? var = 0.21300034290246206 est appelé.

De ce test, il semble que le navigateur Web ne mette pas la page en cache, mais mette en cache l’URL de l’iframe, puis effectue une nouvelle demande sur cette URL mise en cache. Cependant, je ne comprends toujours pas comment résoudre ce problème.

Quelqu'un a-t-il une idée sur la manière d'empêcher le navigateur Web de mettre en cache des URL iframe?

76
JR.

Faites pointer l'URL de l'iframe sur une page de votre site servant de proxy pour extraire et renvoyer le contenu réel de l'iframe. Maintenant, vous n'êtes plus lié par la politique de même origine (EDIT: n'empêche pas le problème de mise en cache de l'iframe).

0
kmoser

C'est un bug dans Firefox:

https://bugzilla.mozilla.org/show_bug.cgi?id=356558

Essayez cette solution de contournement:

<iframe src="webpage2.html?var=xxx" id="theframe"></iframe>

<script>
var _theframe = document.getElementById("theframe");
_theframe.contentWindow.location.href = _theframe.src;
</script>
46
Caleb

J'ai pu contourner ce bogue en définissant un attribut name unique sur l'iframe - pour une raison quelconque, cela semble détruire le cache. Vous pouvez utiliser les données dynamiques dont vous disposez en tant qu'attribut name - ou simplement le temps actuel en ms ou en ns, quelle que soit la langue utilisée pour les modèles. C'est une solution plus intéressante que celles décrites ci-dessus car elle ne nécessite pas directement JS.

Dans mon cas particulier, l'iframe est construit via JS (mais vous pouvez faire la même chose via PHP, Ruby, peu importe), alors j'utilise simplement Date.now():

return '<iframe src="' + src + '" name="' + Date.now() + '" />';

Cela corrige le bug dans mes tests; probablement parce que le window.name dans la fenêtre interne change.

27
STRML

C'est un bug dans Firefox 3.5.

Jetez un coup d'oeil .. https://bugzilla.mozilla.org/show_bug.cgi?id=279048

3
renga

Comme vous l'avez dit, le problème ici n'est pas la mise en cache de contenu iframe, mais la mise en cache d'URL iframe.

Depuis septembre 2018, il semble que le problème se pose toujours dans Chrome, mais pas dans Firefox.

J'ai essayé beaucoup de choses (ajouter un paramètre GET changeant, effacer l'url de l'iframe dans onbeforeunload, détecter un "rechargement à partir du cache" à l'aide d'un cookie, configurer différents en-têtes de réponse) et voici les deux seules solutions qui ont fonctionné de moi:

1- Facile: créez votre iframe dynamiquement à partir de javascript

Par exemple:

const iframe = document.createElement('iframe')
iframe.id = ...
...
iframe.src = myIFrameUrl 
document.body.appendChild(iframe)

2- Manière conjuguée

Côté serveur, comme expliqué ici , désactivez la mise en cache du contenu que vous servez pour l'iframe OU de la page parent (cela suffira).

ET

Définissez l'URL d'iframe à partir de javascript avec un paramètre de recherche supplémentaire, tel que celui-ci:

const url = myIFrameUrl + '?timestamp=' + new Date().getTime()
document.getElementById('my-iframe-id').src = url

(version simplifiée, méfiez-vous des autres paramètres de recherche)

3
steph643

Pour que l'iframe charge toujours le nouveau contenu, ajoutez le timestamp Unix actuel à la fin des paramètres GET. Le navigateur la considère alors comme une requête "différente" et cherchera un nouveau contenu.

En Javascript, cela pourrait ressembler à:

frames['my_iframe'].location.href='load_iframe_content.php?group_ID=' + group_ID + '&timestamp=' + timestamp;
3
Division Six

J'ai défini l'attribut iframe src plus tard dans mon application. Pour supprimer le contenu mis en cache à l'intérieur d'iframe au début de l'application, je fais simplement:

myIframe.src = "";

... quelque part au début du code js (par exemple dans le gestionnaire jquery $ ())

Merci à http://www.freshsupercool.com/2008/07/10/firefox-caching-iframe-data/

2
janekw

J'ai trouvé ce problème dans le dernier Chrome ainsi que dans le dernier Safari sur Mac OS X au 17 mars 2016. Aucun des correctifs ci-dessus ne fonctionnait pour moi, y compris l'attribution de src à vider puis sur certains sites, ou l'ajout de un paramètre "nom" nommé de manière aléatoire, ou l'ajout d'un nombre aléatoire à la fin de l'URL après le hachage, ou l'attribution de la fenêtre de contenu href à la commande src après l'attribution de la commande src.

Dans mon cas, c’est parce que j’utilisais Javascript pour mettre à jour l’IFRAME et que je changeais seulement le hachage dans l’URL.

La solution de contournement dans mon cas était que j'ai créé une URL intermédiaire avec une redirection méta de 0 seconde vers cette autre page. Cela se produit si vite que je remarque à peine l'écran qui clignote. De plus, la couleur d’arrière-plan de la page intermédiaire a été identique à celle de l’autre page et vous la remarquez encore moins.

2
Volomike

J'ai également eu ce problème en 2016 avec iOS Safari. Ce qui semblait fonctionner pour moi était En donnant un paramètre GET à l'iframe src et une valeur correspondante 

<iframe width="60%" src="../other/url?cachebust=1" allowfullscreen></iframe>

0