[APACHE DOCUMENTATION]

Apache HTTP Server Version 1.3

Négociation de contenu

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.


A propos de la négociation de contenu

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.

Négociation dans Apache

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 :

Utilisation d'un fichier de transcodage de types

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:
l'URI du fichier contenant la variante (pour le type de média donné , encodé selon l'encodage du contenu). Ces URI sont interprétées en tant qu'URL relatives par rapport à celle du fichier de transcodage; elles doivent être sur le même serveur (!), et doivent pointer des fichiers auxquels le client aurait accès s'il étaient adressés directement.
Content-type:
type média --- jeu de caractère, des paramètres de niveau et de qualité (qs) peuvent y être adjoints. La combinaison du type média et du jeu de caractère est aussi souvent appelée type MIME ; les types de média typiques sont par exemple : image/gif, text/plain, ou text/html; level=3.
Content-language:
La langue de la variante, spécifiée sous la forme du code standard de langue d'Internet (ex., en pour l'anglais, kr pour le coréen, etc.).
Content-encoding:
Si le fichier est compressé ou encodé par une autre méthode, plutôt que fournissant les données brutes, ce champ précise quelle est la technique utilisée. Pour des fichiers compressés (le seul cas qui conduit couramment à l'utilisation de ce champ), l'encodage de contenu vaudra x-compress, ou x-gzip, selon le cas.
Content-length:
La taille du fichier. Les clients peuvent demander à recevoir un certain type de média seulement si la taille de la variante correspondante n'est pas trop grande ; la technique consistant à spécifier cette taille dans le fichier de transcodage permet au serveur de traiter ce paramètre de requête et de faire les bons choix sans avoir à ouvrir le fichier.

Multiviews

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.

L'Algorithme de négociation

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.

Dimensions de Négociation

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.

Algorithme de négociation d'Apache

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 :

  1. Premièrement, pour chacune des dimensions de négociation, le champ d'en-tête Accept approprié est vérifié et un facteur de qualité est calculé pour chaque variante des types spécifiés. Si le champ d'en-tête Accept pour cette dimension implique que cette variante n'est pas acceptable, alors l'algorithme l'élimine. Si toutes les variantes disponibles ont été éliminées lors de cette phase, sauter au pas 4.
  2. La sélection de la "meilleure" variante se fait par élimination. Chacun des tests suivants est appliqué dans cet ordre précis. Toute variante non sélectionnée à un étage de test est éliminée. Après chaque test, si seule une variante unique reste, elle est alors considérée comme le "meilleur choix possible". Tant qu'il reste plusieurs variantes, le serveur active un test supplémentaire.
    1. Multiplication du facteur de qualité de l'en-tête Accept par le facteur de qualité-de-source pour le type média correspondant à la variante testée, puis sélection des plus fortes valeurs.
    2. Sélection des variantes de plus fort facteur de qualité pour la langue
    3. Sélection des variantes correspondant de préférence aux choix de langues demandées, soit en se basant sur l'ordre de ces langues soit sur la directive 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.
    4. Sélection des variantes de plus haute valeur du paramètre 'level' (utilisé pour numéroter les versions de documents de type text/html).
    5. Sélection des variantes non encodées, s'il existe simultanément des variantes brutes et encodées. Si toutes ou aucunes de variantes ne sont encodées, on les sélectionnera toutes.
    6. Sélection des variantes disposant d'un jeu de caractère acceptable, selon les spécifications du champ Accept-Charset d'en-tête. Le Jeu ISO-8859-1 sera toujours accepté. Toute variante non explicitement associée à un jeu de caractères est supposée de type ISO- 8859-1.
    7. Sélection des variantes de plus faible taille
    8. Sélection de la première variante trouvée parmi celles qui restent (cela peut être la première vue dans le fichier de transcodage, ou la première apparaissant dans le répertoire) et passer à l'étape 3.
  3. L'algorithme a à présent sélectionné la "meilleure" variante, et peut alors la retourner au client. Le champ Vary de l'en-tête HTTP dans la réponse sera renseigné pour indiquer les dimensions de négociation traitées (cette information est particulièrement destinée aux proxies et aux navigateurs lorsqu'ils enregistrent le document en cache). Fin de traitement.
  4. Si vous arrivez à ce point, aucune variante n'a pu être sélectionnée (car aucune ne peut être acceptée par le client). Renvoyer un code d'erreur 406 (signifiant "Pas de représentation acceptable") avec un corps de réponses consistant en un document HTML donnant la liste des variantes disponibles. Le champ Vary de l'en-tête HTTP de réponse sera renseigné pour rappeler les dimensions de négociation.

Optimiser l'usage des valeurs de qualité

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.

Types de média avec metacaractères

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.

Variantes sans indication de langue

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é.

Note sur le cache

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.


Apache HTTP Server Version 1.3

Index

Version française © Valery Fremaux / EISTI 1998