El soporte de Apache para la negociación de contenidos ha sido actualizado para adecuarse a la especificación HTTP/1.1. Apache puede escoger la mejor representación de un recurso basado en las preferencias proporcionadas por el navegador (browser) para los distintos tipos de medios, idiomas, conjunto de de caracteres y codificación. También proporciona un par de características que dan una mayor inteligencia en el manejo de peticiones de los navegadores cuando envían información de negociación incompleta.
El módulo mod_negotiation es el encargado de proveer la negociación de contenido y ya viene compilado por defecto.
Un recurso puede estar disponible en diferentes representaciones. Por ejemplo, puede estar disponible en diferentes idiomas o en diferentes tipos de medio o una combinación de ambos. Una manera de tomar la decisión adecuada es la de dar al usuario una página índice y dejarle elegir. Sin embargo, a menudo es posible que el servidor haga una selección automáticamente. Esto funciona porque los navegadores pueden enviar como parte de su petición información sobre qué representación prefieren. Por ejemplo, un navegador podría indicar que prefiere ver información en francés y, si no fuera posible, en inglés. Los navegadores indican sus preferencias a través de cabeceras en la petición. Para pedir representaciones únicamente en francés, el navegador podría enviar algo así:
Accept-Language: fr
Tenga en cuenta que esta preferencia se aplicará únicamente cuando haya una posibilidad de elección de representaciones y éstas varían por idioma.
Como ejemplo de una petición más compleja, digamos que el navegador ha sido configurado para aceptar francés e inglés, pero la preferencia es francés, y también ha sido configurado para aceptar varios tipos de medio, siendo el preferente HTML antes que texto plano o cualquier otro tipo de texto y configurado también para que GIF o JPEG sean los preferentes sobre cualquier otro tipo de medio, pero también permitiendo cualquier otro tipo de medio como último recurso:
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 soporta negociación de contenido "guiado por el servidor", tal y como los define la especificación HTTP/1.1. Soporta plenamente peticiones de cabecera de tipo Accept, Accept-Language, Accept-Charset y Accept-Encoding. Apache 1.3.4 también soporta negociación de contenido "transparente", que es un protocolo de negociación experimental definido en RFC 2295 y RFC 2296. No obstante, no ofrece soporte para "negociación de características" (feature negotiation) como la definen estas RFCs.
Un recurso es una entidad conceptual identificada por un URI (RFC 2396). Un servidor HTTP como Apache proporciona acceso a representaciones de recurso(s) dentro de su espacio de nombres, siendo cada representación en forma de una secuencia de bytes con un tipo de medio definido, un conjunto de caracteres, codificación, etc. Cada recurso puede ser asociado con cero, uno o más de una representación en un momento dado. Si hay disponibles múltiples representaciones, se referencia al recurso como negotiable (negociable) y cada uno de sus representaciones como variant (variante). Las maneras en las que las variantes para un recurso negociable varían se llaman dimensions (dimensiones) de la negociación.
Para que un servidor pueda negociar un recurso, necesita que se le proporcione información sobre cada una de las variantes. Esto se hace de una de estas maneras:
*.var
) que
nombre los ficheros que contengan explícitamente a las variantes.Un tipo mapa es un documento que se asocia con el manejador llamado type-map
(también conocido de tipo mime application/x-type-map
) por cuestiones de
compatibilidad con versiones anteriores de Apache). Tenga en cuenta que para utilizar esta
característica debe tener un manejador configurado que defina un sufijo de fichero como
type-map
. La manera idónea de hacerlo es poner lo siguiente en el fichero de
configuración del servidor:
AddHandler type-map .var
Véanse los comentarios en el fichero de configuración para más detalles.
Los ficheros de tipo mapa tienen una entrada para cada variante disponible. Estas entradas consisten en líneas de cabecera contiguas en formato HTTP. Las entradas para diferentes variantes se separan con líneas en blanco. Las líneas en blanco no están permitidas dentro de una entrada. Existe el acuerdo de empezar un fichero mapa con una entrada para la entidad combinada como un todo (aunque esto no se requiere, y si está presente, será ignorado). A continuación se muestra un ejemplo de un fichero mapa:
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 las variantes tienen calidades origen (source qualities) diferentes, esto se puede indicar con el parámetro "qs" al tipo de medio:
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
Los valores de qs pueden tomar valores en el rango comprendido entre 0.000 y 1.000. Tenga en cuenta que cualquier variante con un valor de qs igual a 0.000 nunca será elegido. A las variantes sin un parámetro qs se les da como valor 1.0. El parámetro qs indica la "calidad" relativa de esta variante comparada con el resto de variantes disponibles, independientemente de las capacidades del cliente. Por ejemplo, un fichero jpeg normalmente es de mayor calidad que un fichero ascii si se intenta representar una fotografía. Sin embargo, si la fuente que se quiere representar es ascii, la representación ascci tendrá una mayor calidad que un jpeg. De este modo, un valor qs es específico de una variante dada dependiendo de la naturaleza de la fuente que representa.
La lista completa de cabeceras reconocidas es la siguiente:
URI:
Content-Type:
image/gif
, text/plain
o
text/html; level=3
.
Content-Language:
en
para el inglés, kr
para el coreano etc.)
Content-Encoding:
x-compress
para ficheros comprimidos
y x-gzip
para ficheros comprimidos con gzip.
El prefijo x-
es ignorado en comparaciones de codificación.
Content-Length:
Description:
Las MultiViews
es una opción por cada directorio, o sea que puede ser
configurado la directiva Options
dentro de <Directory>
,
<Location>
o <Files>
en access.conf
o
(si se configura AllowOverride
) en ficheros .htaccess
files.
Tenga en cuenta que Options All
no configura MultiViews
; usted
debe preguntar especificar su nombre.
MultiViews
actúa de la siguiente manera: si el servidor recibe una petición
para /directorio/fichero
y /directorio/fichero
tiene habilitado
MultiViews
y /directorio/fichero
no existe,
entonces el servidor lee el directorio en busca de ficheros llamados fichero.* "falsifica"
un tipo mapa que nombra a aquellos, asignándoles los mismos tipos de medio y codificaciones
de contenido que tendrían si el cliente hubiera preguntado por uno de ellos por nombre.
El servidor escogería entonces el que mejor se ajustara a los requerimientos del cliente.
MultiViews
se puede usar también para búsquedas de ficheros referidos en la
directiva DirectoryIndex
, si el servidor está tratando de indexar un
directorio. Si los ficheros de configuración especifican algo como
DirectoryIndex indexel servidor elegirá entre
index.html
y index.html3
si ambos
están presentes. Si ninguno de ellos existe y index.cgi
está, el servidor
lo ejecutará.
Si uno de los ficheros que encuentra cuando lea la directiva es un script CGI, no está claro qué es lo que pasaría. El código da esto un tratamiento especial: si la petición es de tipo POST o de tipo GET con QUERY_ARGS o PATH_INFO, al script se le da un ratio de calidad extremadamente alto. De otro modo se le da un ratio de calidad extremadamente bajo, lo que generalmente provoca que una de las otras vistas (si es que hay alguna) sea recuperada.
Después de que Apache haya obtenido una lista de variantes para un recurso, tanto desde un fichero tipo mapa o desde un fichero en el directorio, invoca uno de dos métodos posibles para decidir cuál es la mejor variante que devolver, si existe alguna. Para usar las características de negociación de contenido de Apache, no es necesario conocer ninguno de los detalles de cómo una negociación se da. A pesar de ello y para los interesados, este documento explica los métodos que se utilizan.
Existen dos métodos de negociación:
Dimensión | Notas |
---|---|
Tipo de medio | El navegador indica preferencias con el campo cabecera Accept header field. Cada elemento puede tener un factor de calidad asociado. La descripción de variante puede tener también un factor de calidad (el parámetro "qs"). |
Idioma | El navegador indica las preferencias con el campo de cabecera Accept-Language. Cada elemento puede tener un factor de calidad. Las variantes se pueden asociar con ninguno, uno o más de un idioma. |
Codificación | El navegador indica preferencias con el campo de cabecera Accept-Encoding. Cada elemento puede tener un factor de calidad. |
Conjunto de caracteres | El navegador indica preferencias en el campo de cabecera Accept-Charset. Cada elemento puede tener un factor de calidad. Las variantes pueden indicar un conjunto de caracteres como parámetro del tipo de medio. |
Apache puede usar el siguiente algoritmo para seleccionar la mejor variante (si hay alguna) y devolverla al navegador. Este algoritmo no es muy configurable y opera del siguiente modo:
LanguagePriority
.text/*
no explícitamente asociadas con un conjunto de
caracteres particular son asumidas como ISO-8859-1.A veces Apache cambia los valores de cualidad esperados en base a una estricta interpretación del algoritmo de negociación expuesto arriba. Esto se produce para obtener un mejor resultado del algoritmo para los navegadores que no envían una información completa o adecuada. Algunos de los navegadores más extendidos envían información de la cabecera Accept que daría en muchos casos como resultado la selección del variant erróneo. Si el navegador envía información completa y correcta, no se aplicará la manipulación.
Accept: petición de cabecera indica preferencias para tipos de medio. Puede incluir también tipos de medio con caracteres comodín, tales como "image/*" o "*/*", en el que * significa cualquier cadena. Así que una petición del tipo:
Accept: image/*, */*indicaría que cualquier tipo que comience con "image/" es aceptable, del mismo modo que lo sería cualquier otro (el ejemplo anterior, "image/*", es redundante). Algunos navegadores envían caracteres comodín de manera rutinaria además de los tipos explícitos que pueden manejar. Por ejemplo:
Accept: text/html, text/plain, image/gif, image/jpeg, */*
La intención de esto es la de indicar que los tipos explícitamente listados son los preferidos, pero que si existe una representación diferente, también es correcto. Sin embargo, bajo el algoritmo básico, tal como se mostró más arriba, los caracteres comodín */* tienen exactamente igual preferencia que los otros tipos, así que no son los preferidos. El navegador debería haber enviado una petición con un valor de calidad (preferencia) más baja para */*, tal como:
Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01
Los tipos explícitos no tienen ningún factor de calidad, de modo que toman el valor de preferencia 1.0 (el más alto). Al carácter comodín se le da un valor de preferencia bajo de 0.0.1, por lo que otros tipos sólo serán devueltos si ningún variant concuerda con un tipo explícitamente listado.
Si la cabecera Accept: no no contiene factores q de ningún tipo, Apache fija el valor q de "*/*", si existe, a 0.01 para emular el comportamiento deseado. También fija el valor q de los caracteres comodín del formato "type/*" a 0.02, por los que estos son los preferidos en vez de "*/*". Si cualquier tipo de medio en la cabecera Accept: contiene un factor q, estos valores especiales no se aplican, así que las peticiones desde navegadores que envían la información correcta de comienzo funcionan como se esperaba.
Si algunos de los variant para un recurso en particular tienen un atributo de idioma y algunos otros no, a estos sin idioma se les da un factor de calidad de idioma muy bajo: 0.001.
La razón para configurar este factor de calidad a un valor tan bajo es la de permitir que se proporcione un variant por defecto cuando ninguno de los otros variant concuerde con las preferencias de idioma del navegador.
Por ejemplo, considere la situación con tres variants:
El significado de un variant sin idioma es que siempre es aceptable por el navegador. Si la cabecera Accept-Language incluye "en" o "fr" (o ambos), bien se devolverá el fichero foo.en.html, o bien el fichero foo.fr.html. Si el navegador no muestra ni "en" ni "fr", como aceptables, entonces se usará foo.html.
Apache amplía el protocolo de negociación transparente de contenido (RFC 2295) de la
siguiente manera. Se utiliza un nuevo elemento de tipo {encoding ..}
en las listas de variant para etiquetar variants que sólo están disponibles con una
sola codificación de contenido. La implementación del algoritmo RVSA/1.0 (RFC 2296)
es ampliado para reconocer variants codificados en la lista y para usarlos como
candidatos cada vez que su codificación sea aceptable de acuerdo a la petición en
la cabecera Accept-Encoding. La implementación de RVSA/1.0 no "redondea" los factores
de calidad a 5 dígitos decimales antes de escoger el mejor variant.
Si está utilizando negociación de idioma, puede escoger entre diferentes convenciones de nombres ya que los ficheros pueden tener más de una extensión y el orden de las extensiones es generalmente irrelevante (vea el documento mod_mime para más detalles).
Un fichero normal y corriente tiene una extensión de tipo MIME (por ejemplo, , html), quizás una extensión de codificación (como, por ejemplo, gz) y por supuesto una extensión de idioma (por ejemplo, en) cuando tenemos diferentes variants de idioma para ese fichero.
Ejemplos:
Algunos ejemplos de ficheros junto con hiperenlaces válidos y no válidos:
Fichero | Hiperenlace válido | Hiperenlance no válido |
---|---|---|
foo.html.en | foo foo.html |
- |
foo.en.html | foo | foo.html |
foo.html.en.gz | foo foo.html |
foo.gz foo.html.gz |
foo.en.html.gz | foo | foo.html foo.html.gz foo.gz |
foo.gz.html.en | foo foo.gz foo.gz.html |
foo.html |
foo.html.gz.en | foo foo.html foo.html.gz |
foo.gz |
Mirando la tabla anterior, notará que es siempre posible usar en un hiperenlace el nombre sin ninguna extensión (por ejemplo, foo). La ventaja es que usted puede ocultar el tipo de fichero rsp de un documento y cambiarlo más tarde, por ejemplo, de html a shtml o cgi sin tener que cambiar las referencias del hiperenlace.
Si usted quiere continuar usando un tipo MIME en sus hiperenlances (por ejemplo foo.html), la extensión de idioma (incluyendo una extensión de codificación, si existe) debería estar en la parte derecha de la extensión de tipos MIME (por ejemplo, foo.html.en).
Cuando un caché almacena una representación, lo asocia con la URL pedida. La próxima vez que la URL sea pedida, el caché podrá utilizar la representación en caché. Pero, si el recurso es negociable en el servidor, esto dará lugar a que solamente el primer variant pedido esté en caché y que los las siguientes coincidencias con la caché den respuestas erróneas. Para prevenir esto, Apache normalmente marca todas las respuestas que son devueltas después de una negociación de contenido como "no cacheables" por los clientes HTTP/1.0. Apache también soporta las características del protocolo de HTTP/1.1 para permitir el "cacheado" de respuestas negociadas.
Para las respuestas que vienen de un cliente compatible con HTTP/1.0 (tanto un navegador o una caché), se puede utilizar la directiva CacheNegotiatedDocs para permitir el "cacheado" de respuestas que están sujetas a negociación. Esta directiva puede ser especificada en la configuración del servidor o del host virtual y no toma ningún argumento. No tiene ningún efecto sobre peticiones de clientes HTTP/1.1.