Estoy intentando construir un marco de sitio web compatible estándar que sirva XHTML 1.1 como application/xhtml + xml o HTML 4.01 como texto/html dependiendo del soporte del navegador. Actualmente solo busca "application/xhtml + xml" en cualquier lugar del encabezado accept, y lo usa si existe, pero eso no es flexible - text/html podría tener una puntuación más alta. Además, se volverá más complejo cuando se agreguen otros formatos (WAP, SVG, XForms, etc.). Entonces, ¿alguien sabe de una pieza probada de código PHP para seleccionar, a partir de una matriz de cadenas dada por el servidor, ya sea la mejor soportada por el cliente o una lista ordenada basada en la puntuación del cliente?Cómo seleccionar el tipo de contenido del encabezado HTTP Accept en PHP
Respuesta
Puede aprovechar apache's mod_negotiation module. De esta forma puede usar toda la gama de capacidades de negociación que ofrece el módulo, incluyendo sus propias preferencias para el tipo de contenido (e, g, "Realmente deseo entregar la aplicación/xhtml + xml, a menos que el cliente prefiera algo más "). solución básica:
- crear un archivo .htaccess con
AddHandler type-map .var
como contenidos - crear un archivo con foo.var
URI: foo
como contenidos
URI: foo.php/html Content-type: text/html; qs=0.7
URI: foo.php/xhtml Content-type: application/xhtml+xml; qs=0.8 - crear un archivo con foo.php
<?php echo 'selected type: ', substr($_SERVER['PATH_INFO'], 1);
como contenido. - solicitud http://localhost/whatever/foo.var
Para que esto funcione necesita mod_negotiation habilitado, los privilegios apropiados para AllowOverride AddHandler y AcceptPathInfo no ser discapacitado por $ _SERVER [ 'PATH_INFO'].
Con mi Firefox enviando "Aceptar: texto/html, application/xhtml + xml, application/xml; q = 0.9, /; q = 0.8" y el ejemplo del mapa .var el resultado es "tipo seleccionado: xhtml" .
Puede utilizar otros "ajustes" para deshacerse de PATH_INFO o la necesidad de solicitar foo .var, pero el concepto básico es: dejar que mod_negotiation redirija la solicitud a su script php de forma que el script pueda "leer" el tipo de contenido seleccionado.
Así que, ¿alguien sabe de una pieza de probada eficacia de código PHP para seleccionarNo es una solución PHP puro, pero yo diría que mod_negotiation ha sido probado ;-)
http://www.dev-archive.net/articles/xhtml.html#content-negotiation está escrito en Perl, pero está claramente establecido y solo consta de algunos if/else y regex. Portarlo a PHP debería ser trivial.
pequeño fragmento de mi biblioteca:
function getBestSupportedMimeType($mimeTypes = null) {
// Values will be stored in this array
$AcceptTypes = Array();
// Accept header is case insensitive, and whitespace isn’t important
$accept = strtolower(str_replace(' ', '', $_SERVER['HTTP_ACCEPT']));
// divide it into parts in the place of a ","
$accept = explode(',', $accept);
foreach ($accept as $a) {
// the default quality is 1.
$q = 1;
// check if there is a different quality
if (strpos($a, ';q=')) {
// divide "mime/type;q=X" into two parts: "mime/type" i "X"
list($a, $q) = explode(';q=', $a);
}
// mime-type $a is accepted with the quality $q
// WARNING: $q == 0 means, that mime-type isn’t supported!
$AcceptTypes[$a] = $q;
}
arsort($AcceptTypes);
// if no parameter was passed, just return parsed data
if (!$mimeTypes) return $AcceptTypes;
$mimeTypes = array_map('strtolower', (array)$mimeTypes);
// let’s check our supported types:
foreach ($AcceptTypes as $mime => $q) {
if ($q && in_array($mime, $mimeTypes)) return $mime;
}
// no mime-type found
return null;
}
ejemplo de uso:
$mime = getBestSupportedMimeType(Array ('application/xhtml+xml', 'text/html'));
solo una pequeña mejora: cambie el prototipo de función a 'function getBestSupportedMimeType ($ mimeTypes = null, $ acceptedTypes = FALSE) {if ($ acceptedTypes === FALSE) {$ acceptedTypes = $ _SERVER ['HTTP_ACCEPT']; } ... '. esencialmente permite tipos de aceptación personalizados si el programa necesita hacer algo un poco más personalizado. – chacham15
PEAR :: HTTP 1.4.1 tiene un método string negotiateMimeType(array $supported, string $default)
<?php
require 'HTTP.php';
foreach(
array(
'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5',
'text/*;q=0.3, text/html;q=0.8, application/xhtml+xml;q=0.7, */*;q=0.2',
'text/*;q=0.3, text/html;q=0.7, */*;q=0.8',
'text/*, application/xhtml+xml',
'text/html, application/xhtml+xml'
) as $testheader) {
$_SERVER['HTTP_ACCEPT'] = $testheader;
$http = new HTTP;
echo $testheader, ' -> ',
$http->negotiateMimeType(array('application/xhtml+xml', 'text/html'), 'application/xhtml+xml'),
"\n";
}
impresiones
text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, /;q=0.5 -> application/xhtml+xml text/*;q=0.3, text/html;q=0.8, application/xhtml+xml;q=0.7, */*;q=0.2 -> text/html text/*;q=0.3, text/html;q=0.7, */*;q=0.8 -> application/xhtml+xml text/*, application/xhtml+xml -> application/xhtml+xml text/html, application/xhtml+xml -> text/html
edición : esto podría no ser tan bueno después de todo ...
Mi Firefox envía Accept: text/html, application/xhtml + xml, application/xml; q = 0,9, /; q = 0,8
text/html y aplicación/xhtml + xml tener q = 1,0 pero PEAR :: HTTP (afaik) no permite que elija cuál prefiere, devuelve texto/html sin importar lo que pase como $ compatible. Esto puede o no ser suficiente para ti. ver mis otras respuestas.
Para el código de PHP 5, use el paquete HTTP2: http://pear.php.net/package/HTTP2 – cweiske
Sólo para el registro , Negotiation es una implementación pura de PHP para manejar la negociación de contenido.
Merged @ maciej-Łebkowski y @ chacham15 soluciones con mis problemas arreglos y mejoras. Si pasa $desiredTypes = 'text/*'
y Accept
contiene text/html;q=1
, entonces se devolverá text/html
.
/**
* Parse, sort and select best Content-type, supported by a user browser.
*
* @param string|string[] $desiredTypes The filter of desired types. If &null then the all supported types will returned.
* @param string $acceptRules Supported types in the HTTP Accept header format. $_SERVER['HTTP_ACCEPT'] by default.
* @return string|string[]|null Matched by $desiredTypes type or all accepted types.
* @link Inspired by http://stackoverflow.com/a/1087498/3155344
*/
function resolveContentNegotiation($desiredTypes = null, $acceptRules = null)
{
if (!$acceptRules) {
$acceptRules = @$_SERVER['HTTP_ACCEPT'];
}
// Accept header is case insensitive, and whitespace isn't important.
$acceptRules = strtolower(str_replace(' ', '', $acceptRules));
$sortedAcceptTypes = array();
foreach (explode(',', $acceptRules) as $acceptRule) {
$q = 1; // the default accept quality (rating).
// Check if there is a different quality.
if (strpos($acceptRule, ';q=') !== false) {
// Divide "type;q=X" into two parts: "type" and "X"
list($acceptRule, $q) = explode(';q=', $acceptRule, 2);
}
$sortedAcceptTypes[$acceptRule] = $q;
}
// WARNING: zero quality is means, that type isn't supported! Thus remove them.
$sortedAcceptTypes = array_filter($sortedAcceptTypes);
arsort($sortedAcceptTypes, SORT_NUMERIC);
// If no parameter was passed, just return parsed data.
if (!$desiredTypes) {
return $sortedAcceptTypes;
}
$desiredTypes = array_map('strtolower', (array) $desiredTypes);
// Let's check our supported types.
foreach (array_keys($sortedAcceptTypes) as $type) {
foreach ($desiredTypes as $desired) {
if (fnmatch($desired, $type)) {
return $type;
}
}
}
// No matched type.
return null;
}
No debe filtrar q = 0 desde los encabezados Aceptar del cliente. Significa que el cliente no aceptará ese tipo, p. 'Accept-Language: en, en-US; q = 0' significa que aceptaré cualquier inglés siempre que no sea estadounidense. –
PEAR's HTTP2 library apoya analizar todos los tipos de Accept
cabeceras. Se puede instalar a través de composer y PEAR.
Los ejemplos se pueden encontrar en documentation o my blog post.
El cliente puede aceptar una lista de tipos de mimo en la respuesta. Por otro lado, el orden de la respuesta es muy importante para el lado del cliente. PHP Pear HTTP2 es lo mejor para tratar con el lenguaje, el conjunto de caracteres y los tipos miméticos.
$http = new HTTP2();
$supportedTypes = array(
'text/html',
'application/json'
);
$type = $http->negotiateMimeType($supportedTypes, false);
if ($type === false) {
header('HTTP/1.1 406 Not Acceptable');
echo "You don't want any of the content types I have to offer\n";
} else {
echo 'I\'d give you data of type: ' . $type . "\n";
}
Aquí es un buen tutorial: https://cweiske.de/tagebuch/php-http-negotiation.htm
- 1. encabezado HTTP Accept significa
- 2. Configuración del encabezado HTTP Accept para JsonRestStore
- 3. ¿Cuál es la función del encabezado HTTP "Vary: Accept"?
- 4. Cómo forzar navegador para establecer conjunto de caracteres en el encabezado HTTP de tipo de contenido
- 5. No puedo cambiar el encabezado de solicitud HTTP Valor de tipo de contenido usando jQuery
- 6. PHP eliminar encabezado HTTP
- 7. ¿Cómo interpretar el encabezado HTTP Aceptar vacío?
- 8. Cómo especificar el encabezado "Vary: Accept-Encoding" en .htaccess
- 9. El uso de cabecera HTTP Accept-charset
- 10. Cómo establecer el encabezado de tipo de contenido de WebClient?
- 11. ¿Cómo se especifica el conjunto de caracteres en el encabezado de respuesta de tipo de contenido HTTP?
- 12. ¿Cómo se configuran los campos de encabezado Accept y Accept-Language?
- 13. Encabezado HTTP - ntCoent-Length
- 14. ¿Cuándo podría el encabezado del host HTTP ser indefinido?
- 15. encabezado de longitud de contenido de php se sobrescribe!
- 16. Establezca el encabezado HTTP en UTF-8 usando PHP
- 17. ¿Cómo cambiar el tipo de contenido en php?
- 18. PHP obtener el código de respuesta del encabezado http sin cURL
- 19. En XPath cómo seleccionar el contenido del elemento
- 20. ¿Cómo puedo obtener el contenido del archivo cargado en php?
- 21. carriles 3 formato de respuesta y control de versiones utilizando el tipo de proveedor MIME en el encabezado Accept
- 22. redirect_to con encabezado HTTP
- 23. ¿Cómo obtener el contenido de solicitud (cuerpo) en PHP?
- 24. Tipo de contenido HTTP advertencia de video/mp4 en firefox
- 25. ¿Longitud del contenido y otros encabezados HTTP?
- 26. WCF Soap Actions en el encabezado HTTP o encabezado SOAP?
- 27. PHP Obtenga el contenido de HTTP 400 Response
- 28. NSURLRequest configurar el encabezado HTTP
- 29. ¿cómo funciona el encabezado en php?
- 30. ¿Cómo obtengo el contenido de una solicitud http en Ruby?
Mientras que todo está bien tratar de ser compatible con los estándares y "hacer las cosas bien", creo que es digno de pasar un momento de considerar si realmente va a obtener ningún beneficio de todo esto. P.ej. no es una buena razón para suministrar application/xhtml + xml cuando text/html funciona bien y así sucesivamente. –