Nouveau dans Symfony 8.2 (en développement). Entre l'application et le lecteur, une réponse traverse plusieurs caches : un CDN, parfois un proxy, puis le navigateur. Tous lisent le même Cache-Control. Or ils ne se valent pas : le CDN, on sait le purger quand un article change ; le navigateur, jamais. Une page gardée une journée par le CDN l'était aussi par chaque navigateur, et un correctif publié à midi restait invisible à qui avait lu le matin.
Des en-têtes ciblés
La RFC 9213 permet d'écrire, à côté de Cache-Control, un en-tête destiné à un seul cache : CDN-Cache-Control pour les CDN, ou un nom propre au fournisseur. Le cache qui reconnaît son en-tête l'applique et ignore Cache-Control ; les autres l'ignorent. Symfony 8.2 les écrit pour vous :
$response->setMaxAge(0)->setPrivate(); $response->cacheControl('CDN') ->setMaxAge(3600) ->setStaleWhileRevalidate(60);
Cache-Control: max-age=0, private CDN-Cache-Control: max-age=3600, stale-while-revalidate=60
stale-while-revalidate laisse le CDN servir la copie périmée pendant qu'il en redemande une fraîche ; stale-if-error la lui fait servir si l'application ne répond plus.
Et pour voir ce que fait le cache ?
La même version ajoute Cache-Status (RFC 9211) au cache HTTP de Symfony : framework.http_cache.cache_status: 'Symfony' fait dire à chaque réponse si elle vient du cache (Symfony; hit; ttl=58) ou de l'application (Symfony; fwd=miss; stored). Il n'entre pas dans cet exercice, mais c'est l'outil pour vérifier ce que vous allez écrire.
À faire
Dans JournalController :
- Un article : le CDN le garde une journée (
86400), avec 60 s destale-while-revalidateet une heure destale-if-error. Le navigateur le revalide à chaque visite :max-age=0, private. - La une : cinq minutes au CDN, une minute partout ailleurs (
public). - Le panier ne change pas : il ne concerne que le navigateur, et n'a rien à dire au CDN.
L'onglet « Requêtes » montre les en-têtes de chaque réponse.