Довольно простой вопрос: какой из этих двух заголовков PHP (версия 5+) является «лучшим»?
header('Not Modified', true, 304); header('HTTP/1.1 304 Not Modified');
Я уверен, что первый из них является самым многовалютным, но просто любопытно, если PHP «исправит» второй, если по HTTP 1.0 …
Благодаря!
Изменить: один из этих заголовков разбивает PHP на моем веб-хосте. Последующий вопрос: PHP header () вызывает скрипт «сбой» с ошибкой HTTP 500
Я бы использовал это:
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);
$_SERVER['SERVER_PROTOCOL']
содержит протокол, используемый в запросе, например HTTP/1.0
или HTTP/1.1
.
Редактировать Я должен признать, что мое предложение бессмысленно. После нескольких тестов я заметил, что если первый параметр является допустимой строкой состояния HTTP , PHP будет использовать эту строку состояния, независимо от того, был ли и какой второй код состояния указан третьим параметром. И второй параметр (имена документации, которые он заменяет ) тоже бесполезен, так как не может быть нескольких строк состояния.
Таким образом, второй и третий параметры в этом вызове просто избыточны:
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);
Вместо этого используйте это:
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
Есть две вещи о поведении первого заголовка, который стоит указать:
Я бы пошел со вторым, поскольку аргумент кода ответа HTTP поддерживается только> = PHP 4.3.0 (что может повлиять на переносимость кода).
Я делал это много раз и не встречал ни одного клиента, который не поддерживает HTTP / 1.1, поэтому, если у вас нет специального случая, я не должен думать, что это будет проблемой.
Обычно я бы пошел со вторым примером – однако, когда недавно тестировал приложение, использующее apachebench, мы часто заметили, что он висит.
После отладки было определено, что заголовок в этом стиле:
header('HTTP/1.1 304 Not Modified')
Был преступником (да, я понятия не имею), и после его изменения,
header('Not Modified', true, 304);
Верьте или нет, а начал работать. Очень странно, но о чем подумать. Вероятно, я буду использовать второй метод в будущем.
Для дальнейшего использования функция http_response_code () находится в 5.4:
http://www.php.net/manual/en/function.http-response-code.php
Альтернативой является:
if (!function_exists('http_response_code')) { function http_response_code($code = NULL) { if ($code !== NULL) { switch ($code) { case 100: $text = 'Continue'; break; case 101: $text = 'Switching Protocols'; break; case 200: $text = 'OK'; break; case 201: $text = 'Created'; break; case 202: $text = 'Accepted'; break; case 203: $text = 'Non-Authoritative Information'; break; case 204: $text = 'No Content'; break; case 205: $text = 'Reset Content'; break; case 206: $text = 'Partial Content'; break; case 300: $text = 'Multiple Choices'; break; case 301: $text = 'Moved Permanently'; break; case 302: $text = 'Moved Temporarily'; break; case 303: $text = 'See Other'; break; case 304: $text = 'Not Modified'; break; case 305: $text = 'Use Proxy'; break; case 400: $text = 'Bad Request'; break; case 401: $text = 'Unauthorized'; break; case 402: $text = 'Payment Required'; break; case 403: $text = 'Forbidden'; break; case 404: $text = 'Not Found'; break; case 405: $text = 'Method Not Allowed'; break; case 406: $text = 'Not Acceptable'; break; case 407: $text = 'Proxy Authentication Required'; break; case 408: $text = 'Request Time-out'; break; case 409: $text = 'Conflict'; break; case 410: $text = 'Gone'; break; case 411: $text = 'Length Required'; break; case 412: $text = 'Precondition Failed'; break; case 413: $text = 'Request Entity Too Large'; break; case 414: $text = 'Request-URI Too Large'; break; case 415: $text = 'Unsupported Media Type'; break; case 500: $text = 'Internal Server Error'; break; case 501: $text = 'Not Implemented'; break; case 502: $text = 'Bad Gateway'; break; case 503: $text = 'Service Unavailable'; break; case 504: $text = 'Gateway Time-out'; break; case 505: $text = 'HTTP Version not supported'; break; default: exit('Unknown http status code "' . htmlentities($code) . '"'); break; } $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0'); header($protocol . ' ' . $code . ' ' . $text); $GLOBALS['http_response_code'] = $code; } else { $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200); } return $code; } }
В этом примере я использую $ GLOBALS, но вы можете использовать любой механизм хранения, который вам нравится … Я не думаю, что есть способ вернуть текущий код состояния:
https://bugs.php.net/bug.php?id=52555
Для справки коды ошибок, которые я получил из исходного кода PHP:
http://lxr.php.net/opengrok/xref/PHP_5_4/sapi/cgi/cgi_main.c#354
И как отправляется текущий HTTP-заголовок с использованием переменных:
Я думаю, что ответ Гумбо является самым разумным до сих пор. Однако попробуйте следующее:
<?php header('Gobbledy Gook', true, 304); ?>
Если первая строка не является надлежащим заголовком, она отбрасывается. Если iy действительно выглядит как допустимый заголовок, он добавляется к заголовкам – попробуйте следующее:
<?php header('Cache-Control: max-age=10', true, 304); ?>
Руководство для header () и обратите внимание на особые случаи – в общем, я считаю, что не рекомендуется полагаться на такую встроенную эвристику.
Тем не менее, я предполагаю, что на самом деле вы заинтересованы в том, чтобы контент был хорошо кэширован прокси-серверами / браузерами. В большинстве случаев латентность – это скорее проблема проблемы, чем пропускная способность. Далее рассмотрите, как работает браузер, когда кешированный контент устарел – в отсутствие обновленной информации кэширования он продолжает повторять запросы на сервер, чтобы узнать, все ли содержимое остается устаревшим.
Т.е. в большинстве случаев игнорирование условной части запросов (или даже лучше их удаление на веб-сервере) фактически повышает производительность.