Le support d'Apache pour la négociation de contenu a été remise à jour pour se confirmer à la spécification HTTP/1.1. Apache peut choisir la meilleure représentation pour une ressource sur la base d'informations de préférences fournies par le navigateur pour chaque type de média, langage, jeu de caractère et encodage. Il implémente de plus une paire de fonctionnalités qui lui permettent une gestion plus intelligente des requêtes émise à partir de navigateurs qui envoient des informations de négociation incomplètes.
La négociation de contenu est implémentée par le module mod_negotiation, compilé par défaut.
Une ressource peut être délivrée sous plusieurs représentations. Par exemple, elle peut être présente en plusieurs langues ou sous différents types de média, ou encore une combinaison de ces deux variantes. Une des façons de permettre à un utilisateur de choisir la meilleure représentation est de l'aiguiller sur une page d'index, et le laisser choisir. Il est cependant souvent possible d'automatiser ce choix à partir du serveur. Ceci est rendu possible par l'envoi, par le navigateur, d'un certain nombre d'informations associées à la requête qui précisent la représentation préférentielle. Par exemple, un navigateur peut indiquer qu'il désire voir l'information en Français, si possible, et en anglais sinon. Les navigateurs indiquent ces préférences par des éléments d'en- tête dans la requête. Pour demander expressément une version française, le navigateur inclurait ceci
Accept-Language: fr
Notez que cette préférence ne pourra être appliquée que lorsque le choix de représentation existe, ce qui dépend évidemment du langage demandé.
Pour donner un exemple d'une requête plus compliquée, nous considérerons que le navigateur est configuré pour accepter les version françaises et anglaises, avec une préférence marquée pour la version française, et de plus, accepte plusieurs types de média, avec encore une préférence marquée pour le HTML par rapport à un type "plain text" ou tout autre type textuel, et une préférence marquée pour les types GIF ou JPEG plutôt que tout autre format graphique, tout en autorisant tous les autres types en dernier recours :
Accept-Language: fr; q=1.0, en; q=0.5 Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1
Apache 1.2 supporte la négiciation de contenu 'pilotée du serveur', telle que définie dans la spécification HTTP/1.1. Il reconnaît parfaitement les champs Accept, Accept-Language, Accept-Charset et Accept-Encoding dans les en-têtes de requêtes HTTP.
Les termes utilisés pour parler de négociation de contenu sont : une ressource est un objet qui peut être demandé à un serveur, et qui dont le choix peut résulter de l'application d'un algorithme de négociation de contenu. Si la ressource est disponibles sous plusieurs formes, ces diverses formes sont appelées représentations ou variantes. Les paramètres différentiant les différentes variantes d'une ressource sont appelés dimensions de négociation.
Pour négocier la représentation d'une ressource, le serveur doit connaître l'information permettant de caractériser les variantes. Ceci peut être fait par l'un des deux moyens suivants :
*.var
) qui nomme explicitement les fichiers
contenant les diverses variantes Une table de transcodage de types est un document associé
à un handler, appelé type-map
(ou, pour
assurer la compatibilité arrière avec des versions plus
anciennes d'Apache, le fichier de types MIME application/x-type-
map
). Notez que pour utiliser cette fonctionnalité, il
vous faudra définir une directive SetHandler
qui
indiquera quel est le suffixe à considérer pour les
type-map
; Ceci est parfaitement réalisé
par l'écriture :
AddHandler type-map var
dans srm.conf
. Voir les commentaires dans les
fichiers de configuration d'exemple pour plus de détails.
Les fichiers de transcodage de type disposent d'une entrée par variante; ces entrées consistent en des lignes d'en- têtes contiguës au format RFC822. Les entrées pour différentes variantes sont séparées par des lignes vides. Ces lignes vides sont d'ailleurs illégales au sein d'une entrée. Par convention on commencera une table de transcodage par une entrée désignant l'entité comme un tout (bien que ceci ne soit ni obligatoire, ni même exploité pour l'instant). Un exemple de fichier de transcodage est :
URI: foo URI: foo.en.html Content-type: text/html Content-language: en URI: foo.fr.de.html Content-type: text/html; charset=iso-8859-2 Content-language: fr, de
Si les variantes présentent une "qualité subjective" différente, ceci peut être indiqué par le paramètre "qs" en regard du type de média, comme pour l'image suivante par exemple (disponible en jpeg, gif, ou ASCII- art):
URI: foo URI: foo.jpeg Content-type: image/jpeg; qs=0.8 URI: foo.gif Content-type: image/gif; qs=0.5 URI: foo.txt Content-type: text/plain; qs=0.01
les valeurs de qs peuvent évoluer de 0.000 à 1.000. Notez que toute variante présentant une qualité de 0.000 ne sera jamais choisie. Par défaut, le serveur considère que 'qs' vaut 1.0.
La liste complète des champs d'en-tête reconnus est :
- URI:
Content-type:
image/gif
, text/plain
, ou
text/html; level=3
. Content-language:
en
pour
l'anglais, kr
pour le coréen, etc.). Content-encoding:
x-compress
, ou x-gzip
, selon
le cas. Content-length:
Il s'agit d'une option par répertoire, ce qui signifie
qu'elle peut être instituée par une directive
Options
dans une section <Directory>
,
<Location>
ou <Files>
dans le
fichier access.conf
, ou (si AllowOverride
est correctement déclaré) dans des fichiers
.htaccess
. Notez que la mention Options All
ne valide pas le mode MultiViews
; vous devrez
explicitement demander ce mode par son nom. (Il est possible de
contourner cette limite par la modification d'une seule ligne dans le
fichier http_core.h
).
L'effet du mode MultiViews
est le suivant : si le
serveur reçoit une requête dirigée vers
/some/dir/foo
, et si le mode MultiViews
est
activé pour /some/dir
, et enfin si
/some/dir/foo
(sans extensions, par exemple comme sous-
répertoire) n'existe pas, alors le serveur
recherchera dans le répertoire des fichiers s'appelant foo.*,
les rassemble comme s'il s'agissait de la même entité,
en leur assignant à chacun le type de média qu'ils
auraient s'ils avaient été requis directement par leur
nom complet. Le serveur puise alors dans cet ensemble de fichier
celui qui correspond le mieux à la demande du client.
Ceci s'applique aux recherches effectuées sur les fichiers
nommés par la directive DirectoryIndex
, si l'URL
de requête vise un répertoire ; si le fichier de
configuration spécifie
DirectoryIndex index
alors le serveur fera l'arbitrage entre les fichiers
index.html
et index.html3
si les deux
existent. Si aucun de ces deux fichiers sont présents, et par
contre qu'un fichier index.cgi
y est, le serveur
exécutera ce dernier.
Si l'un des fichiers trouvé lors de la lecture de la directive est un script CGI, le comportement obtenu n'est pas toujours celui qui parait le plus évident. Le code traite ce cas de façon particulière --- si la requête était du type POST, ou GET avec des arguments QUERY_ARGS ou PATH_INFO, une note de qualité maximale est généralement attribuée au script, lequel est selon toute logique en général exécuté ; dans tous les autres cas une note de qualité la plus faible lui est attribuée, ce qui conduit à servir préférentiellement toute autre version présente.
Une fois la liste des différentes variantes obtenues pour une ressource, soit à partir d'un fichier de transcodage des types, soit à partir des extensions de noms de fichiers, Apache applique l'algorithme qui lui permet de "décider" quelle est la meilleure variante à renvoyer, pour autant qu'il y en ait une. Pour ceci, il calcule un facteur de qualité pour chacune des variantes dans chacune des dimensions de négociation. Il n'est cependant pas nécessaire de connaître tous les détails du processus de négociation pour pouvoir utiliser cette fonctionnalité d'Apache. La suite de ce document explique néanmoins en détail ce que fait cet algorithme pour "ceuce que ça intéresserait".
Dans certaines circonstances, Apache peut "induire" le facteur de qualité dans une dimension particulière pour arriver à de meilleurs résultats. La manière qu'utilise Apache pour "intuiter" ce facteur est expliqué en détails ci-après.
Dimension |
Notes |
Type Média |
Le navigateur affiche ses préférences dans un champ Accept: de l'en-tête. Chaque préférence peut être associée à un facteur de qualité. Les descriptions de variantes peuvent aussi être associées à un tel facteur. |
Langage |
Le navigateur affiche ses préférences en matière de langue dans un champ Accept-Language: de l'en- tête. Chaque choix peut être associé à un facteur de qualité. Les variantes peuvent être associées à aucune, une ou plusieurs langues. |
Encodage |
Le navigateur affiche ses préférences par le champ Accept-Encoding: de l'en-tête. |
Jeu de caractères |
Le navigateur affiche ses préférences dans un champ Accept-Charset: de l'en-tête. Les variantes peuvent mentionner un jeu de caractère comme paramètre du type de média. |
Apache utilise un algorithme pour déterminer la variante la plus "appropriée" en fonction de la requête cliente (si elle existe). Cet algorithme n'est pas paramétrable. Il fonctionne ainsi :
LanguagePriority
(si présente), ou par
défaut sur l'ordre des langues mentionnées dans le
champ Accept-Language de l'en-tête de requête. Apache modifie parfois les facteurs de qualité par rapport à ce qu'ils seraient par la stricte application de l'algorithme ci-dessus. Ceci est fait pour obtenir de meilleurs résultats pour des navigateurs qui n'envoient pas des informations de négociation complètes ou même juste. Quelques uns des navigateurs courants envoient des champs Accept, qui sans cette optimisation, conduiraient à un choix erroné. Si le navigateur envoie une information de négociation complète et correcte, cette optimisation ne sera pas effectuée.
Le champ d'en-tête Accept: indique les préférences de types de média. La définition de ces types de média peut aussi inclure des metacaractères, comme dans "image/*" ou "*/*" dans lesquelles * remplace une chaîne quelconque. De ce fait, une requête inscrivant :
Accept: image/*, */*
indiquerait que tout type commençant par "image/" est acceptable, comme le serait d'ailleurs tout autre type (le premier "image/*" est ici redondant). Certains navigateurs ont l'habitude d'ajouter à la liste des types demandés un type globalisant. Par exemple :
Accept: text/html, text/plain, image/gif, image/jpeg, */*
Leur intention est d'indiquer que les types explicitement cités sont attendus préférentiellement, mais qu'ils sont prêt à accepter tout type de remplacement par défaut. Malheureusement, notre algorithme n'institue pas de priorité entre la mention */* et les autres mentions explicites. Le navigateur aurait du envoyer une requête en précisant un facteur de qualité faible pour le metatype *.*, telle que :
Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01
Les types explicites ne sont pas qualifiés en termes de qualité, et sont associés par défaut à une préférence de 1.0 (la plus haute). Le métatype */* a une préférence explicite de 0.01, ce qui implique que tout type non explicite ne sera envoyé que s'il n'y a vraiment pas d'autre solution.
Si le champ Accept: ne contient aucun facteur q, Apache induit un facteur q de 0.01 pour le metatype "*/*" s'il le détecte, afin de simuler le comportement attendu. Apache induit en outre un facteur q de 0.02 pour tout metatype de la forme "type/*" (de manière à les rendre préférentiels par rapport au type quelconque déduit de "*/*"). Si au moins un des types explicites dans le champ Accept: est associé à un facteur q, ces valeurs induites ne seront pas appliquées, et les requêtes émises par des navigateurs conformes auront bien l'effet attendu.
Si certaines des variantes pour une ressource particulière ont un attribut de langue, et certaines autres en sont dépourvues, ces dernières seront associées à un facteur de qualité de langue très faible de 0.001.
La raison conduisant à "induire" ce très faible facteur de qualité pour les variantes non spécifiées en termes de langue est de permettre la mise à disposition d'une variante par défaut qui sera renvoyée si la négociation de langue échoue pour toutes les variantes explicitées. Par exemple, considérez la situation suivante mettant en scène trois variantes :
La troisième variante est par définition toujours acceptable par un navigateur sur le plan de la langue. Si l'en- tête de requête Accept-Language précise soit "en" ou "fr" (ou les deux) l'un des deux fichiers foo.en.html ou foo.fr.html sera renvoyé. Si le navigateur ne précise ni "fr" ni "en" comme langues acceptées, foo.html sera retourné.
Lorsqu'un document est enregistré en cache, il est associé à son URL utilisée dans la requête. La prochaine requête sur cette URL est détectée, et le document enregistré dans le cache est servi, si sa date de péremption n'est pas passée. Mais si la ressource est sujette à une négociation de contenu par le serveur, seule la variante envoyée serait enregistrée en cache, et des requêtes suivantes pourraient renvoyer une version qui n'est pas celle demandée. Pour éviter ceci, Apache marque toutes les réponses obtenues par négociation de contenu comme étant des documents non enregistrables en cache par les clients HTTP/1.0. Apache supporte aussi les fonctionnalités HTTP/1.1 permettant le cache de réponses négociées.
Pour les requêtes provenant de clients conformes au HTTP/1.0 (soit un navigateur, soit un cache), la directive CacheNegotiatedDocs peut être utilisée pour permettre l'enregistrement en cache des réponses sujettes à négociation. Cette directive peut être écrite dans un contexte de configuration serveur ou d'hôte virtuel, et n'accepte aucun argument. Elle n'a aucun effet sur les requêtes au format HTTP/1.1.
Version française © Valery Fremaux / EISTI 1998