Próbuję zbudować standardową, zgodną ze standardem witrynę internetową, która obsługuje XHTML 1.1 jako application/xhtml + xml lub HTML 4.01 jako text/html w zależności od obsługi przeglądarki. Obecnie po prostu szuka "application/xhtml + xml" w dowolnym miejscu w nagłówku accept i używa go, jeśli istnieje, ale to nie jest elastyczne - tekst/html może mieć wyższy wynik. Ponadto stanie się bardziej skomplikowany, gdy dodane zostaną inne formaty (WAP, SVG, XForms itp.). Czy ktoś wie o wypróbowanym i przetestowanym fragmencie kodu PHP do wyboru, z tablicy łańcuchów podanej przez serwer, albo najlepiej obsługiwanej przez klienta, albo uporządkowanej listy na podstawie wyniku klienta?Jak wybrać typ zawartości z nagłówka HTTP Accept w PHP
Odpowiedz
Możesz wykorzystać apache's mod_negotiation module. W ten sposób możesz wykorzystać pełny zakres możliwości negocjacyjnych oferowanych przez moduł, w tym dla twoich preferencji dla typu zawartości (e, g, "Naprawdę chcę dostarczyć aplikację/xhtml + xml, chyba że klient bardzo woli coś innego "). podstawowe rozwiązanie:
- utworzyć plik .htaccess z
AddHandler type-map .var
jako zawartość - stworzyć foo.var plików z
URI: foo
jako zawartość
URI: foo.php/html Content-type: text/html; qs=0.7
URI: foo.php/xhtml Content-type: application/xhtml+xml; qs=0.8 - stworzyć foo.php plików z
<?php echo 'selected type: ', substr($_SERVER['PATH_INFO'], 1);
jako zawartość. - prośba http://localhost/whatever/foo.var
Aby to zadziałało trzeba mod_negotiation włączone odpowiednie przywileje AllowOverride dla AddHandler i AcceptPathInfo nie zostanie wyłączona za $ _SERVER [ 'PATH_INFO'].
Z moim Firefox wysyłanie "Zaakceptuj: tekst/html, aplikacja/xhtml + xml, aplikacja/xml; q = 0.9, /; q = 0,8" i przykładowa mapa .var wynik jest "wybrany typ: xhtml" .
Możesz użyć innych "poprawek", aby pozbyć się PATH_INFO lub potrzeby żądania foo .var, ale podstawową koncepcją jest: niech mod_negotiation przekieruje żądanie do skryptu php w sposób, który skrypt może "odczytać" wybrany typ zawartości.
Więc, czy ktoś wie o sprawdzonej kawałek kodu PHP aby wybraćTo nie jest czysty roztwór php ale powiedziałbym mod_negotiation został sprawdzony ;-)
http://www.dev-archive.net/articles/xhtml.html#content-negotiation jest napisany w języku Perl, ale jest wyraźnie rozplanowany i składa się z niektórych elementów if/else i regex. Przeniesienie go do PHP powinno być trywialne.
mały fragment z mojej biblioteki:
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;
}
Przykład użycia:
$mime = getBestSupportedMimeType(Array ('application/xhtml+xml', 'text/html'));
tylko odrobinę ulepszenie: zmień prototyp funkcji na 'function getBestSupportedMimeType ($ mimeTypes = null, $ acceptedTypes = FALSE) {if ($ acceptedTypes === FALSE) {$ acceptedTypes = $ _SERVER ['HTTP_ACCEPT']; } ... '. zasadniczo pozwalają niestandardowe typy akceptacji, jeśli program musi zrobić coś bardziej niestandardowego. – chacham15
Pear :: HTTP 1.4.1 ma metodę 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";
}
nadrukami
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
edycji : w końcu może nie być tak dobrze ...
My zapalić wysyła Accept: text/html, application/xhtml + xml, application/xml, Q = 0,9, / q = 0,8
text/html i application/xhtml + xml ma q = 1.0, ale PEAR :: HTTP (afaik) nie pozwala, aby wybrałeś, który wolisz, zwraca tekst/html bez względu na to, co przekazujesz jako $ support. To może, ale nie musi, być dla ciebie wystarczające. zobacz moją drugą odpowiedź (odpowiedzi).
Dla kodu PHP 5 użyj pakietu HTTP2: http://pear.php.net/package/HTTP2 – cweiske
Tylko dla rekordu , Negotiation to czysta implementacja PHP do obsługi negocjacji treści.
Scalono rozwiązania @ maciej-Łebkowski i @ chacham15 z rozwiązaniami problemów i ulepszeniami. Jeśli podasz $desiredTypes = 'text/*'
i Accept
zawiera text/html;q=1
, zostanie zwrócony 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;
}
Nie można odfiltrować q = 0 z nagłówków Accept klienta. Oznacza to, że klient nie zaakceptuje tego typu, np. 'Accept-Language: en, en-US; q = 0' oznacza, że zaakceptuję dowolny angielski, o ile nie jest amerykański. –
PEAR's HTTP2 library obsługuje parsowania wszystkie rodzaje Accept
nagłówków. Można go zainstalować przez composer i PEAR.
Przykłady można znaleźć na stronie documentation lub my blog post.
Klient może zaakceptować listę typów mime w odpowiedzi. Z drugiej strony kolejność odpowiedzi jest bardzo ważna dla strony klienta. PHP Pear HTTP2 to najlepiej radzić sobie z językiem, charset i mimetypes.
$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";
}
Oto dobry poradnik: https://cweiske.de/tagebuch/php-http-negotiation.htm
- 1. Korzystanie z nagłówka HTTP Accept-charset
- 2. Jak ustawić domyślny typ zawartości w Spring MVC w nagłówku Accept Accept?
- 3. Django nie analizuje niestandardowego nagłówka http accept
- 4. RestSharp Accept zmiana nagłówka
- 5. HttpURLConnection GET request z nagłówkiem http "Accept"
- 6. kątowe, typ zawartości nie jest wysyłany z $ http
- 7. Jak uzyskać typ zawartości pliku w PHP?
- 8. Jak interpretować pusty nagłówek HTTP Accept?
- 9. REST API - Użyj nagłówka HTTP "Accept: application/json"
- 10. Jak zmienić typ zawartości w php?
- 11. Jak dodać Accept nagłówka z tekstem/csv w jQuery ajax
- 12. JQuery getJSON() nie ustawia poprawnie nagłówka Accept?
- 13. Jak przeanalizować żądanie HTTP z brakującym typem zawartości w Express/NodeJs, przyjmując domyślny typ zawartości?
- 14. PHP SoapClient(): wyślij nagłówek HTTP "User-Agent" i "Accept"
- 15. Wysyła żądanie zwijania bez nagłówka Accept?
- 16. Jak zmienić typ zawartości w obsługi wyjątków
- 17. Nie można zastąpić nagłówka zawartości w s3
- 18. Wysyłanie ogólnej zawartości-typ w służbie
- 19. Server usuwa pól nagłówka HTTP zwyczaj
- 20. Negocjacja/kompresja zawartości HTTP: Użyj Base64 z Accept-Encoding/Content-Encoding?
- 21. Jak usunąć Nginx z nagłówka odpowiedzi HTTP?
- 22. Brak nagłówka autoryzacji w żądaniu PHP POST
- 23. Określ typ obrazu z bazy 64 zawartości
- 24. Niestandardowy typ zawartości - czy rejestracja jest obowiązkowa?
- 25. Ustawienie żądania wysyłki JAX-WS Typ zawartości
- 26. Umieszczanie niestandardowego nagłówka http w szkielecie
- 27. Problem Axis2 w ustawieniu nagłówka HTTP SOAPAction
- 28. Nginx domyślny typ zawartości
- 29. php serwer nginx dostaje dziwne nagłówka i umieszczać dane z żądania http
- 30. Jak ustawić typ zawartości nagłówka żądania podczas korzystania z funkcji pobierania APi
Chociaż to wszystko jest dobre, aby spróbować i być zgodny ze standardami i „robić rzeczy właściwe”, myślę, że warto poświęcić chwilę zastanowić się, czy będzie rzeczywiście uzyskać żadnych korzyści z to wszystko. Na przykład. nie ma wiele powodów, by dostarczyć aplikację/xhtml + xml, gdy tekst/HTML działa dobrze i tak dalej. –