Я пытаюсь создать стандартную структуру веб-сайта, которая поддерживает XHTML 1.1 как application / xhtml + xml или HTML 4.01 как text / html в зависимости от поддержки браузера. В настоящее время он просто ищет «application / xhtml + xml» в любом месте заголовка accept и использует это, если он существует, но это не является гибким. Text / html может иметь более высокий балл. Кроме того, он станет более сложным, когда будут добавлены другие форматы (WAP, SVG, XForms и т. Д.). Итак, знает ли кто-нибудь о проверенном и проверенном фрагменте кода PHP для выбора из строкового массива, заданного сервером, либо наилучшего, поддерживаемого клиентом, либо упорядоченного списка на основе оценки клиента?
Вы можете использовать модуль mod_negotiation от apache . Таким образом, вы можете использовать весь спектр возможностей для переговоров, предлагаемый модулем, включая ваши собственные предпочтения для типа контента (e, g, «Я действительно хочу доставить приложение / xhtml + xml, если только клиент не предпочитает что-то еще») , основное решение:
Карта типа AddHandler .var
как содержание
URI: foo
URI: foo.php / html Content-type: text / html; QS = 0,7
URI: foo.php / xhtml Content-type: application / xhtml + xml; QS = 0,8
как содержание
<? PHP echo 'selected type:', substr ($ _ SERVER ['PATH_INFO'], 1);
как содержание.
Для этого вам необходимо включить mod_negotiation, соответствующие привилегии AllowOverride для AddHandler и AcceptPathInfo не будут отключены для $ _SERVER ['PATH_INFO'].
С моей отправкой Firefox «Accept: text / html, application / xhtml + xml, application / xml; q = 0.9, / ; q = 0.8» и пример .var map, результат «selected type: xhtml».
Вы можете использовать другие «настройки», чтобы избавиться от PATH_INFO или необходимость запросить foo .var , но основная концепция: пусть mod_negotiation перенаправляет запрос на ваш php-скрипт таким образом, что скрипт может «читать» выбранный контент- тип.
Итак, кто-нибудь знает о проверенной и проверенной части кода PHP для выбора
Это не чисто php-решение, но я бы сказал, что mod_negotiation проверена и проверена 😉
Маленький фрагмент из моей библиотеки:
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; }
пример использования:
$mime = getBestSupportedMimeType(Array ('application/xhtml+xml', 'text/html'));
Pear :: HTTP 1.4.1 имеет строку метода negotiateMimeType (массив $ поддерживается, строка $ 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"; }
печать
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
редактирование: возможно, это не так хорошо …
Мой firefox отправляет Accept: text / html, application / xhtml + xml, application / xml; q = 0.9, / ; q = 0.8
text / html и application / xhtml + xml имеют q = 1.0, но PEAR :: HTTP (afaik) не позволяет вам выбрать, какой из них вы предпочитаете, он возвращает text / html независимо от того, что вы передаете как $. Это может быть или не быть достаточно для вас. см. мой другой ответ (ы).
Только для записи Negotiation – это чистая реализация PHP для ведения переговоров по содержанию.
Merged @ maciej-Łebkowski и @ chacham15 с исправлениями и улучшениями моих проблем. Если вы передадите $desiredTypes = 'text/*'
и Accept
содержит text/html;q=1
то 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; }
Библиотека HTTP2 PEAR поддерживает разбор всех типов заголовков Accept
. Он устанавливается через композитор и PEAR.
Примеры можно найти в документации или моем сообщении в блоге .
http://www.dev-archive.net/articles/xhtml.html#content-negotiation написана на Perl, но она четко изложена и состоит только из некоторых if / else и regex. Портирование его на PHP должно быть тривиальным.
Клиент может принять список типов mime в ответе. С другой стороны, порядок ответа очень важен для клиентской стороны. PHP Pear HTTP2 – лучший способ справиться с языком, кодировкой и миметиками.
$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"; }
Вот хороший учебник: https://cweiske.de/tagebuch/php-http-negotiation.htm