Ce qui se passe
Cloudflare prend désormais en charge l'en-tête Vary dans ses Cache Rules,
sur les plans Free, Pro, Business et Enterprise, depuis le tableau de bord,
l'API Rulesets ou Terraform. Jusqu'ici, servir plusieurs représentations d'une
même URL derrière Cloudflare passait par un détour : renoncer au cache,
reproduire la négociation dans une clé de cache personnalisée, écrire un Worker,
ou se contenter de la fonction réservée aux images.
Pourquoi Vary est si délicat
Vary (RFC 9110) indique au cache quels en-têtes de requête peuvent modifier
la réponse. Sans lui, sur une URL qui renvoie du HTML ou du JSON selon
Accept, la première réponse stockée est servie à tous : le client d'API reçoit
du HTML et son parseur échoue.
Mais l'en-tête ne dit pas quelles différences comptent.
Accept-Language: en-US, fr;q=0.8 et Accept-Language: fr;q=0.8, en-GB
aboutissent à la même page anglaise sur un site qui ne parle qu'anglais,
français et allemand ; comparées octet par octet, ce sont deux entrées. Les
combinaisons explosent — dix valeurs sur trois en-têtes, c'est 1 000 variantes —
et le cache devient exact mais froid : les entrées ne servent presque jamais, se
chassent l'une l'autre et renvoient du trafic vers l'origine. Mark Nottingham,
qui tient Vary pour la partie la plus laide de HTTP, a passé au crible plus de
120 millions de réponses venues de près de 50 000 sites : environ 3 000 varient
sur quatre en-têtes ou plus, certains sur 23, voire 47.
Le réglage : une action par en-tête
L'origine déclare toujours, par Vary, les en-têtes qui comptent ; la règle de
cache décide comment Cloudflare traite leurs valeurs. Une action par défaut
couvre les en-têtes non listés.
| Action | Effet | Usage |
|---|---|---|
normalize |
règles dédiées pour Accept, Accept-Language, Accept-Encoding ; ailleurs, espaces superflus retirés et lignes répétées fusionnées |
en-têtes de négociation — le défaut conseillé |
passthrough |
valeur brute : casse, espaces, ordre et doublons comptent | valeurs en nombre fini, où l'exact compte |
bypass |
la réponse n'est pas stockée | Cookie, User-Agent, tout ce qui est personnel ou illimité |
Vary: * n'est jamais mis en cache, quel que soit le réglage. Avec
normalize, on peut restreindre Accept et Accept-Language aux types et aux
langues réellement servis ; une étiquette régionale comme en-US se réduit
alors à en, sauf à la déclarer telle quelle. La valeur normalisée est aussi
celle que reçoit l'origine, pour que son choix colle à la clé de cache.
Exemple via l'API, avec des valeurs à adapter :
{
"action": "set_cache_settings",
"action_parameters": {
"cache": true,
"vary": {
"default": { "action": "normalize" },
"headers": {
"accept": { "action": "normalize", "media_types": ["text/html", "application/json"] },
"accept-language": { "action": "normalize", "languages": ["fr", "en"] }
}
}
}
}Attention : un PUT sur le point d'entrée de la phase
http_request_cache_settings remplace toutes les règles de cette phase. Si
vous en avez déjà, reprenez-les dans le tableau ou créez la règle seule.
Les pièges côté origine
- Chaque réponse cacheable doit porter le même
Vary, erreurs et réponses de repli comprises. Une seule qui l'oublie est stockée sans variation, puis servie à tout le monde. - Modifier la règle ne purge rien : les anciennes entrées restent jusqu'à
expiration ou purge, y compris après un passage en
bypass. - Clé personnalisée ou Vary ? La clé s'applique à toutes les réponses de la règle, Vary suit ce que déclare l'origine. Mettre le même en-tête dans les deux n'a de sens que si c'est voulu et testé.
Source : We just shipped support for the ugliest part of HTTP: Vary, blog Cloudflare, 22 septembre 2026.