Child pages
  • Éviter les mises en cache de durée imprévisible des fichiers statiques

Problème qu'on a avec la conf apache/tomcat par défaut :

Le résultat est fragile, notamment si on veut modifier un fichier n'ayant pas été modifié depuis longtemps.

Exemple :

  • en mars 2021, une personne accède à https://pod.univ-reunion.fr/static/css/pod.css
  • la date du fichier est 2017-07. Il est donc vieux de 3 ans 6 mois, ou 1340 jours
  • ce fichier est servi par nginx qui renvoie "Last-Modified: ... Jul 2017 ...", mais aucun Expires/Cache-Control
  • n'ayant pas d'instructions précises, le navigateur met en cache le fichier pour 134 jours (10% de 1340)
  • donc si l'utilisateur accède au fichier 4 mois plus tard, le navigateur peut fournir la version dans son cache, sans faire aucune requête vers le serveur
  • si le fichier est modifié, la seule solution possible côté serveur pour s'assurer que l'utilisateur a la dernière version : modifier la page HTML pour faire un lien vers pod.css?v=2021-05 (la valeur importe peu du moment qu'elle est différente)

Solution : forcer une durée fixe de mise en cache

Vincent Bonamy à Rouen a forcé un Cache-Control précis sur ses apaches, du genre : https://www.esup-portail.org/wiki/display/ESUPMU/Optimisation+HTTP+Apache#OptimisationHTTPApache-Cachenavigateur

Pour la majorité des applications cette solution est sans problème. Le seul comportement imprévu concerne les pages qui ne forcent pas de "Cache-Control/Expires" mais qui sont néanmoins potentiellement dynamiques :

  • en PHP par défaut, aucun header cache n'est mis tant qu'une session n'est pas utilisée
  • en tomcat, une jsp simple ne force pas de headers non plus.

Solution proposée sur un reverse proxy

(solution en production à l'université Paris 1 depuis 2018)

Ajouter Cache-Control quand Last-Modified est mis et pas de Expires/Cache-Control

  • pour apache >= 2.4.10 :
Header setifempty Cache-Control "max-age=86400" "expr=-n resp('Last-Modified') && -z resp('Expires')"
  • pour nginx (nécessite lua) :
header_filter_by_lua_block {
  if (not ngx.header["Cache-Control"] and not ngx.header["Expires"] and ngx.header["Last-Modified"]) then
     ngx.header["Cache-Control"] = "max-age=86400"
  end
}

NB : 86400 = 24h

Notes

Squid

squid suit globalement les même règles que les navigateur (cf http://www.squid-cache.org/Doc/config/refresh_pattern/) :

  • si le serveur envoie uniquement Last-Modified, squid va mettre le fichier en cache
  • si le navigateur demande le fichier sans faire reload, il aura le fichier du cache squid.
  • par contre si le navigateur fait un reload ou un force-reload, la requête en reload est propagée sur le serveur

Conclusion : même sur un navigateur vierge, on peut avoir une ancienne version à cause du cache squid.

Durée max de mise en cache de squid pour la conf suggérée "refresh_pattern . 0 20% 4320"

  • conservation 20% => 2 fois plus longue que les 10% du navigateur
  • cache max pour les fichiers n'ayant pas de Cache-Control/Expires : 4320 = 3 jours
  • No labels