Tôi đang cố gắng xây dựng một khung trang web tuân thủ chuẩn phục vụ XHTML 1.1 dưới dạng application/xhtml + xml hoặc HTML 4.01 dưới dạng văn bản/html tùy thuộc vào hỗ trợ của trình duyệt. Hiện tại, nó chỉ tìm kiếm "application/xhtml + xml" ở bất kỳ đâu trong header chấp nhận và sử dụng nếu nó tồn tại, nhưng điều đó không linh hoạt - text/html có thể có điểm số cao hơn. Ngoài ra, nó sẽ trở nên phức tạp hơn khi các định dạng khác (WAP, SVG, XForms vv) được thêm vào. Vì vậy, không ai biết về một đoạn mã PHP đã thử và thử nghiệm để chọn, từ một mảng chuỗi do máy chủ đưa ra, hoặc là chuỗi được hỗ trợ tốt nhất bởi máy khách hoặc danh sách có thứ tự dựa trên điểm số của khách hàng?Cách chọn loại nội dung từ tiêu đề HTTP Accept trong PHP
Trả lời
Bạn có thể tận dụng apache's mod_negotiation module. Bằng cách này, bạn có thể sử dụng đầy đủ các khả năng thương lượng mà mô-đun cung cấp, bao gồm tùy chọn của riêng bạn cho loại nội dung (e, g, "Tôi thực sự muốn phân phối ứng dụng/xhtml + xml, trừ khi khách hàng thích nhiều thứ khác "). giải pháp cơ bản:
- tạo một file .htaccess với
AddHandler type-map .var
như nội dung - tạo ra một tập tin với foo.var
URI: foo
như nội dung
URI: foo.php/html Content-type: text/html; qs=0.7
URI: foo.php/xhtml Content-type: application/xhtml+xml; qs=0.8 - tạo ra một tập tin với foo.php
<?php echo 'selected type: ', substr($_SERVER['PATH_INFO'], 1);
như nội dung. - yêu cầu http://localhost/whatever/foo.var
Để làm việc này bạn cần kích hoạt mod_negotiation, những đặc quyền AllowOverride thích hợp cho AddHandler và AcceptPathInfo không được vô hiệu hóa với $ _SERVER [ 'PATH_INFO'].
Khi Firefox của tôi gửi "Chấp nhận: văn bản/html, ứng dụng/xhtml + xml, ứng dụng/xml; q = 0,9, /; q = 0,8" và ví dụ .var ánh xạ kết quả là "loại đã chọn: xhtml" .
Bạn có thể sử dụng "tinh chỉnh" khác để loại bỏ PATH_INFO hoặc cần phải yêu cầu foo .var, nhưng khái niệm cơ bản là: để mod_negotiation chuyển hướng yêu cầu tới tập lệnh php của bạn theo cách kịch bản có thể "đọc" loại nội dung được chọn.
Vì vậy, không ai biết của một mảnh thử và thử nghiệm mã PHP để chọnNó không phải là một giải pháp php tinh khiết nhưng tôi muốn nói mod_negotiation đã được thử và thử nghiệm ;-)
http://www.dev-archive.net/articles/xhtml.html#content-negotiation được viết bằng Perl, nhưng được trình bày rõ ràng và chỉ bao gồm một số if/else và regex. Chuyển nó sang PHP sẽ là tầm thường.
Ít đoạn từ thư viện của tôi:
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;
}
ví dụ sử dụng:
$mime = getBestSupportedMimeType(Array ('application/xhtml+xml', 'text/html'));
chỉ là một cải tiến tuổi teen: thay đổi nguyên mẫu hàm thành 'hàm getBestSupportedMimeType ($ mimeTypes = null, $ acceptedTypes = FALSE) {if ($ acceptedTypes === FALSE) {$ acceptedTypes = $ _SERVER ['HTTP_ACCEPT']; } ... '. về cơ bản cho phép các loại chấp nhận tùy chỉnh nếu chương trình cần phải làm điều gì đó tùy chỉnh hơn một chút. – chacham15
Pear :: HTTP 1.4.1 có một phương pháp 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";
}
in
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
chỉnh sửa : điều này có thể không tốt cho lắm ...
firefox của tôi gửi Chấp nhận: text/html, application/xhtml + xml, application/xml; q = 0,9, /; q = 0,8
text/html và application/xhtml + xml có q = 1,0 nhưng PEAR :: HTTP (afaik) không cho phép bạn chọn cái nào bạn thích, nó trả về văn bản/html bất kể bạn chuyển qua $ nào. Điều này có thể hoặc có thể không đủ cho bạn. xem (các) câu trả lời khác của tôi.
Đối với mã PHP 5, sử dụng gói HTTP2: http://pear.php.net/package/HTTP2 – cweiske
Chỉ cần cho các hồ sơ , Negotiation là triển khai PHP thuần túy để xử lý thương lượng nội dung.
Đã hợp nhất các giải pháp @ maciej-Łebkowski và @ chacham15 với các vấn đề và cải tiến của tôi. Nếu bạn vượt qua $desiredTypes = 'text/*'
và Accept
chứa text/html;q=1
thì text/html
sẽ được trả lại.
/**
* 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;
}
Bạn không được lọc ra q = 0 từ máy khách Chấp nhận tiêu đề. Điều đó có nghĩa là khách hàng sẽ không chấp nhận loại đó, ví dụ: 'Accept-Language: en, en-US; q = 0' có nghĩa là tôi sẽ chấp nhận bất kỳ tiếng Anh nào miễn là nó không phải là người Mỹ. –
PEAR's HTTP2 library hỗ trợ phân tích cú pháp tất cả các loại tiêu đề Accept
. Nó có thể cài đặt qua composer và PEAR.
Ví dụ có thể được tìm thấy tại documentation hoặc my blog post.
Khách hàng có thể chấp nhận danh sách loại mime trong phản hồi. Mặt khác, thứ tự của phản ứng rất quan trọng đối với phía khách hàng. PHP Pear HTTP2 là cách tốt nhất để xử lý ngôn ngữ, bộ ký tự và 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";
}
Đây là một hướng dẫn tốt: https://cweiske.de/tagebuch/php-http-negotiation.htm
- 1. Sử dụng Accept-charset tiêu đề HTTP
- 2. Tiêu đề loại nội dung http phản hồi JSONP
- 3. Lấy kích thước tệp từ tiêu đề nội dung tải lên nhiều tiêu đề Nội dung độ dài tiêu đề
- 4. PHP: loại bỏ `http: //` từ tiêu đề liên kết
- 5. Bài đăng PHP Curl với tệp đính kèm; tiêu đề loại nội dung tùy chỉnh
- 6. Xóa tiêu đề Loại nội dung trong apache
- 7. Vấn đề đọc nội dung yêu cầu HTTP từ một POST JSON trong PHP
- 8. Độ dài nội dung và các tiêu đề HTTP khác?
- 9. Cách chỉ định bộ ký tự trong tiêu đề phản hồi Kiểu nội dung HTTP?
- 10. Cách nhận nội dung yêu cầu (nội dung) trong PHP?
- 11. PHP remove tiêu đề HTTP
- 12. Các tiêu đề HTTP (Loại nội dung, & c.) Có phân biệt chữ hoa chữ thường không?
- 13. Máy chủ không thể đặt loại nội dung sau khi tiêu đề HTTP đã được gửi
- 14. Giá trị loại nội dung trong yêu cầu HTTP khi tải lên nội dung?
- 15. Có loại Tiêu đề nội dung để thêm HttpResponseHeader không?
- 16. Tiêu đề PHP - Loại nội dung: hình ảnh/jpeg - Không hoạt động cho Internet Explorer
- 17. Tiêu đề HTTP - ntCoent-Length
- 18. Sử dụng nội dung bố trí trong một tiêu đề HTTP response
- 19. Lấy nội dung từ bài đăng http bằng cách sử dụng php CURL
- 20. BOOST ASIO POST HTTP YÊU CẦU - tiêu đề và nội dung
- 21. HTTP POST: yêu cầu tiêu đề có độ dài nội dung?
- 22. Làm thế nào để nắm bắt dữ liệu yêu cầu HTTP đầy đủ (tiêu đề và nội dung) bằng PHP?
- 23. PHP cURL: Bằng tay thiết lập các tiêu đề nội dung có độ dài
- 24. Cách đặt Tiêu đề của Trang từ trang nội dung web trong ASP.NET 3.5
- 25. Cách lấy tiêu đề HTTP
- 26. Cách sử dụng tiêu đề bộ nhớ cache HTTP với PHP
- 27. Máy chủ không thể đặt loại nội dung sau khi tiêu đề HTTP đã được gửi - theo dõi này xuống
- 28. Làm cách nào để đọc nội dung của tiêu đề bố cục nội dung?
- 29. Các tiêu đề HTTP bổ sung này đến từ đâu?
- 30. Cách gửi tiêu đề HTTP trong java
Trong khi đó là tất cả tốt để thử và có tiêu chuẩn phù hợp và "làm những điều đúng", tôi nghĩ rằng nó có giá trị chi tiêu một thời điểm xem xét nếu bạn thực sự sẽ đạt được bất kỳ lợi ích từ tất cả điều này. Ví dụ. không có nhiều lý do để cung cấp ứng dụng/xhtml + xml khi văn bản/html hoạt động tốt và vân vân. –