Intereting Posts
Загружать session_start () только в том случае, если сеанс не существует? Электронная почта говорит, что это от кого Реализация активности пользователя в symfony 2 Лак: как отдельно кешировать страницы на основе значения определенного файла cookie Несколько кнопок отправки php разных действий Изменение номера дисплея JQuery Knob Как проверить, пуст ли текстовый файл в PHP? Как обнаружить и повторить последний гласный в слове? Невозможно выяснить, как запустить mysqli_multi_query и использовать результаты из последнего запроса отправлять электронную почту с прикрепленными файлами в ZF2 Невозможно избавиться от PHP-уведомлений в mPDF Образец текста с использованием библиотеки php GD PHP. Как динамически изменять содержимое страницы при выборе HTML-действия? используйте некоторое время mysql_fetch_array и UPDATE во время цикла Cookies не отправляются туда и обратно в Opera

Как выбрать тип контента из заголовка HTTP Accept в PHP

Я пытаюсь создать стандартную структуру веб-сайта, которая поддерживает 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, если только клиент не предпочитает что-то еще») , основное решение:

  • создать файл .htaccess с
      Карта типа AddHandler .var 

    как содержание

  • создать файл foo.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

    как содержание

  • создать файл foo.php с помощью
      <? PHP
     echo 'selected type:', substr ($ _ SERVER ['PATH_INFO'], 1); 

    как содержание.

  • запросить http: //localhost/whatever/foo.var

Для этого вам необходимо включить 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