XHTML.net

Technology talks by Loïc d’Anterroches

News, articles, PHP, scripts, XHTML/CSS, …

  1. Home
  2. PHP: Hypertext Preprocessor
  3. Pluf - Framework en PHP5

Vary header avec Pluf

The 2008-05-08 at 19:08 by Loïc d'Anterroches filed under Pluf - Framework en PHP5.

Mes expériences avec le système de traduction de Pluf m’ont fait toucher à une en-tête (header) renvoyée par le serveur. Cet en-tête est Vary. Cet en-tête permet d’informer les navigateurs/agents ainsi que les proxy/caches que le contenu d’une page varie en fonction des en-têtes émis par l’agent faisant la requête.

Par exemple, mon navigateur, Firefox, envoie cela comme information quand il faut une requête :

Accept: text/xml,application/xml,application/xhtml+xml,
        text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en,fr;q=0.7,en-us;q=0.3

Cela veut dire, j’accepte du contenu dans différents formats, avec la priorité au format text/xml, puis application/xml, … et à la find image/png et enfin */* tout ce qui reste. Le navigateur accepte aussi le contenu en Anglais, puis Français et Anglais américain. Vous noterez pour certains cas la présence d’un paramêtre q avec une valeur. Ce paramêtre q, comme qualité, avec les langues s’explique de la façon suivante :

en,fr;q=0.7,en-us;q=0.3 correspond en étendu à en;q=1,fr;q=0.7,en-us;q=0.3

Maintenant supposons que vous puissiez accéder au site http://example.com/mon_sujet/ et que ce dernier dispose de 3 versions, une en anglais, une en français et une en américain. Le serveur va maintenant devoir choisir quelle page retourner. Comment choisir ?

Il faut d’abord attribuer une valeur aux trois versions. La valeur correspondera par exemple à la quantité d’information disponible. On va dire que par exemple, la page en Anglais à une qualité de 0.5, la page française de 0.9 et la page américaine de 1.0.

Le résultat du calcul pour chaque langue est le suivant :

  • Anglais : 1.0x0.5 = 0.5
  • Français : 0.7x0.9 = 0.63
  • Américain : 0.3x1.0 = 0.3

C’est donc la page française avec le score le plus haut qui sera retournée. Maintenant, c’est à vous de donner en interne un score pour chaque version de vos pages… en pratique les personnes donnent un score de 1 pour chaque version et donc retourne dans notre cas la version anglaise.

Vous pouvez lire un peu plus sur ces en-tête ici : RFC 2616, Header Field Definitions.

Donc maintenant, vous comprenez que la page http://example.com/mon_sujet/ ne va pas toujours être la même et que le contenu varie en fait par rapport à l’en-tête Accept-Language. Si vous avez maintenant un système de cache naïf, qui stocke une version par URL, cela ne marche pas, car finalement une seule des 3 versions va être mise en cache… problème !

C’est là que l’en-tête Vary du serveur intervient. Cet en-tête dit au système de mise en cache, attention, le contenu de cette page varie en fonction de certaines caractéristiques de la requête. C’est pourquoi on renvoie l’en-tête suivant :

Vary: accept-language

Si vous renvoyez une page qui est en xml ou html en fonction de la requête, vous pourriez mettre :

Vary: accept-language, accept

Il faut donc dans Pluf un moyen élégant de mettre à jour cet en-tête. Je n’ai trouvé qu’une solution pour le moment, mettre dans l’objet requête l’information de la manière suivante :

$request->response_vary_on = 'accept';

Pourquoi sur la requête et pas ajouter manuellement dans la réponse ? Vous pouvez le faire, mais souvent, on n’a pas accès à l’objet réponse. En effet, une vue typiquement ce termine par l’appel suivant :

function mavue($request, $match) 
{ 
    .....
    return Pluf_Shortcuts_RenderToResponse('mongabarit.html', 
                              array('param1' => $toto, ...));
}

Comme vous ne touchez pas à l’objet réponse, il faut trouver une autre solution élégante. Et comme l’objet $request est disponible à tous les niveaux du dispatcher, j’ai donc choisi cette option :

function mavue($request, $match) 
{ 
    .....
    $request->response_vary_on = 'accept';
    return Pluf_Shortcuts_RenderToResponse('mongabarit.html', 
                               array('param1' => $toto, ...));
}

Le problème est que cela fait une condition if supplémentaire pour toutes les vues, que l’en-tête Vary soit utilisé ou non. Cela pose donc une question de performance. Je vais voir si je trouver une méthode plus élégante.

Comments from readers

Voice your ideas

It is painless and I try not to kill electrons in the process.


Your email is required but will not be shared nor displayed.


Do you think your comment will force me to write even better stuff next time? If so, you simply rock.


Logo of Plume CMS