Le WordPress d'aujourd'hui, décodé pour les développeurs

Headless & API

Un CDN Cloudflare devant l’API REST : la clé de cache par langue

Par défaut, Cloudflare met en cache une réponse d'API REST sans tenir compte de la langue demandée. Le correctif tient dans une règle de cache basée sur un en-tête.

Par WordPress Développement • 1 septembre 2020 • 5 min de lecture • Aucun commentaire
Un CDN Cloudflare devant l'API REST : la clé de cache par langue

Un cache CDN ne connaît qu’une chose : l’URL qu’on lui présente. Si un front headless interroge /wp-json/wp/v2/pages/42 pour la version française d’une page, puis la même URL pour sa version anglaise en changeant seulement un en-tête Accept-Language, Cloudflare renverra par défaut la première réponse mise en cache aux deux visiteurs — quelle que soit la langue qu’ils ont réellement demandée.

Ce comportement n’est pas un bug de Cloudflare : c’est la conséquence directe de la façon dont fonctionne une clé de cache HTTP classique, construite sur l’URL et éventuellement quelques en-têtes explicitement déclarés. Sans configuration additionnelle, un en-tête de négociation de contenu comme Accept-Language n’entre jamais dans cette clé.

Le symptôme concret

Sur un projet multilingue avec Polylang, le front interroge la même route REST pour toutes les langues, en distinguant la version voulue soit par un en-tête, soit par un paramètre de requête lang. Une fois un cache Cloudflare activé devant l’API pour soulager le serveur d’origine, le premier visiteur qui charge une page détermine, pour tous les visiteurs suivants, la langue qui sera servie depuis le cache — jusqu’à expiration de la ressource.

Sur un site à fort trafic, ce mélange de langues se produit en quelques minutes seulement après la mise en cache d’une nouvelle route, avant même qu’une alerte de contenu erroné ne remonte côté support.

Deux approches possibles

La première option consiste à inclure la langue dans l’URL elle-même, par exemple /wp-json/wp/v2/pages/42?lang=en, ce qui fonctionne nativement puisque l’URL complète, avec ses paramètres de requête, fait partie de la clé de cache par défaut de Cloudflare.

L'essentiel à retenir : L'en-tête Accept-Language ne suffit pas seul à varier le cache ; Une Cache Key personnalisée règle le problème proprement ; Un en-tête explicite reste plus fiable qu'un en-tête de négociation

La seconde option, utile quand la langue est portée par un en-tête plutôt qu’un paramètre — cas fréquent quand le front décide de la langue côté serveur avant d’appeler l’API — consiste à définir une Cache Key personnalisée qui inclut cet en-tête.

Configurer une Cache Key personnalisée

Cette fonctionnalité, disponible dans les plans Cloudflare Business et supérieurs (ou via un Worker sur les autres plans), permet de déclarer explicitement quels en-têtes doivent varier la clé de cache. La configuration ressemble à ceci dans l’interface Cloudflare, sous Caching > Cache Rules :

{
  "cache_key": {
    "custom_key": {
      "header": {
        "include": ["Accept-Language"]
      }
    }
  }
}

Pour les comptes sans accès à cette fonctionnalité, un Worker permet d’obtenir un résultat équivalent en réécrivant l’URL avant mise en cache, en y ajoutant la langue comme paramètre synthétique :

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const lang = request.headers.get('Accept-Language') || 'fr';
  const url = new URL(request.url);
  url.searchParams.set('_lang_cache', lang.split(',')[0]);
  const cacheKey = new Request(url.toString(), request);
  const cache = caches.default;

  let response = await cache.match(cacheKey);
  if (!response) {
    response = await fetch(request);
    response = new Response(response.body, response);
    response.headers.append('Cache-Control', 's-maxage=3600');
    event.waitUntil(cache.put(cacheKey, response.clone()));
  }
  return response;
}

Un en-tête explicite plutôt qu’une négociation

Dans la pratique, mieux vaut éviter de baser la logique de cache sur Accept-Language tel quel : cet en-tête accepte des listes pondérées (fr-FR,fr;q=0.9,en;q=0.8) qui multiplient artificiellement les variantes de cache pour une même langue effective. Un en-tête personnalisé, décidé par le front et normalisé à une valeur unique par langue, donne un contrôle bien plus net :

  • Le front envoie X-Site-Lang: en plutôt que de laisser passer l’en-tête natif du navigateur.
  • La règle de cache Cloudflare varie sur cet en-tête normalisé, jamais sur la négociation brute.
  • Le nombre de variantes de cache reste borné au nombre de langues réellement gérées par le site.

Variantes utiles

Pour les sites combinant multilinguisme et personnalisation par pays (devise, unités), la même logique s’étend en ajoutant un second en-tête à la Cache Key, par exemple X-Site-Country, en gardant à l’esprit que chaque en-tête ajouté multiplie le nombre d’entrées de cache distinctes à gérer et donc le taux de succès global du cache.

Une règle simple à retenir sur un CDN : tout ce qui varie la réponse doit varier la clé de cache, et rien de plus. Ajouter un en-tête à la clé sans qu’il influence réellement la réponse ne fait que fragmenter le cache pour rien.

En résumé

Le mélange de langues dans un cache CDN n’a rien d’exotique : c’est la conséquence directe d’une clé de cache qui ignore un en-tête pourtant déterminant pour le contenu renvoyé. Une Cache Key personnalisée, ou à défaut un Worker qui rejoue la même logique, referme ce trou en quelques lignes de configuration — sans toucher à la façon dont le contenu est traduit côté WordPress.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi