Протокол HTML. Функции для работы с HTTP-заголовками

Протокол — это набор синтаксических и сематических правил, использующихся при обмене данных между двумя компьютерами, который определяет команды, их синтаксис и порядок отправки, а также очередность отправки команд. Хотя протоколов взаимодействия очень много, веб-разработчики в основном имеют дело с прикладными протоколами и в первую очередь с HTTP-протоколом, который служит для обмена информацией между веб-сервером и браузером (клиентом).

Примечание. Все стандарты в сети Иртернет оформляются в виде RFC-документов; так протокол HTTP описывается главным образом в RFC2616. Ссылки на него можно получить при помощи любой любой поисковой системы.

Работа протокола HTTP не сводится только к передаче сервером HTML-документа по запросу клиента. Помимо HTML-документа, файла или изображения браузер и сервер обмениваются HTTP-заголовками, через которые клиент может сообщить о своих предпочтениях, типе и версии браузера и операционной системы. Сервер, в свою очередь, может сообщить клиенту об ошибочном запросе, "попросить" его установить cookie и т.п. Язык разметки HTML и серверный язык РНР разрабатывались таким образом, чтобы разработчик мог работать без знания HTTP — это позволит отделить уровни протокола и веб-приложения друг от друга. Тем не менее, совершенно абстрагироваться от протокола HTTP не удается, так как его использование зачастую позволяет более гибко управлять работой веб-приложения. В связи с этим в РНР введено несколько инструментов управления протоколом HTTP, которые будут обсуждаться далее в этом разделе:

Помимо этого, будет рассмотрен смежный вопрос преобразования IP-адресов и доменных имен.

Функции для работы с HTTP-заголовками

В ответ на запрос серверу, клиент получает HTTP-документ,который состоит из HTTP-заголовков и тела документа, содержащего HTML-страницу или изображение. HTTP-заголовки, как правило, формируются сервером автоматически и в большинстве случаев веб-разработчику нет надобности отправлятьих в ручную. Впрочем, последнее справедливо только для РНР, тогда как, например, при создании GGI-программы припомощи Perl или С разработчик вынужден самостоятельно реализовывать эту часть HTTP-протокола.

Примечание. HTTP-документ может не содержать тела документа, но всегда содержит HTTP-заголовки.

Браузер, получив HTTP-заголовки, автоматически выполняет предписание, даже не показывая посетителю их содержимое. Таким образом, HTTP-заголовки служат своеобразной метаинформацией, которой сервер и клиент обмениваются скрытно. Впрочем, иногда необходимо вмешиваться в эту скрытую часть работы клиента и сервера, поскольку она управляет многими важными процессами, такими как переадресация, кэширование, аутентификация и т.д. Кроме того скрипты сами могут выступать в роли клиентов, обращаясь к страницам других сайтов: в этом случае они вынуждены брать на себя всю работу по реализации и обработке HTTP-протокола.

Для управления HTTP-заголовками в РНР предназначены функции, представленные в таблице.

Функции для управления HTTP-заголовками

Функция Описание
header() Отправляет HTTP-заголовок
headers_list() Возвращает список отправленных или готовых к отправке HTTP-заголовков
headers_sent() Проверяет отправлены ли HTTP-заголовки

Функция header(), позволяющая отправить клиенту произвольный HTTP-заголовок, имеет следующий синтаксис:

header ($header [, $replace [, $http_response_code]])

Данная функция отправляет HTTP-заголовок $header. Второй параметр $replace определяет поведение интерпретатора РНР, если тот встречает два одинаковых заголовка: если параметр принимает значение true, отправляется последний заголовок, в противном случае — отправляется первый заголовок. Третий параметр $http_response_code позволяет задать код возврата HTTP.

Простейшей процедурой, которую можно осуществить при помощи функции header(), является переадресация, осуществляемая при помощи HTTP-заголовка Location.

Примечание. Вместо полного сетевого адреса (начинающегося с префикса http://) можно использовать относительные адреса: в этом случае браузер сам подставит адрес сайта.

Переадресация при помощи HTTP-заголовка Location

<?php
header("Location: http://sevidi.narod.ru");
?>

В окне веб-браузера это будет выглядеть ТАК.

Механизм HTTP-заголовков дублирован в языке разметки HTTP и добиться схожего поведения можно при помощи передачи HTTP-заголовка через META-тег.

Переадресация средствами HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Переадресация средствами HTML</title>
<META http-equiv="refresh" content="0; URL=http://sevidi.narod.ru">
</head>

<body>
</body>
</html>

В окне веб-браузера это будет выглядеть ТАК.

Если в качестве второго параметра передать функции header() значение true, то все предыдущие HTTP-заголовки с таким же именем будут заменяться последующими.

Переадресация на сайт http://sevidi.narod.ru

<?php
header("Location: http://www.softtime.ru", true);
header("Location: http://sevidi.narod.ru", true);
?>

В окне веб-браузера это будет выглядеть ТАК.

На каждый запрос клиента сервер может возвращать HTTP-код состояния, отражающий вид переадресации при окончательном или временном перемещении документа. Если документ найден и успешно отправлен клиенту, в HTTP-заголовки помещается код состояния 200; если документ не найден — 404; в случае переадресации, клиенту отправляется код состояния 302 — "ресурс временно перемещен". Иногда бывает полезно изменить код состояния на 301 — "ресурс перемещен постоянно".

Изменение состояния кода

<?php
header("Location: http://sevidi.narod.ru", true);
header ("HTTP/1.1 301 Moved Remanently");
?>

В окне веб-браузера это будет выглядеть ТАК.

Коды состояния разделяются на классы, каждый из которых начинается с новой сотни:

Не все коды состояния имеют смысл; часть из них зарезервирована для дальнейших расширений. В таблицах ниже, описываются коды состояния для протокола HTTP 1.1, используемого в настоящее время для распространения HTTP-страниц в сети Интернет.

Информационные HTTP-коды состояния

HTTP-код Описание
100 Continue

Сервер готов получить оставшуюся часть запроса

101 Switching Protocols

Сервер готов переключить протокол приложения на протокол, указанный в заголовке запроса Upgrade, предоставленного клиентом. Переключение должно выполняться, только если указанный протокол имеет преимущество над старым, например, клиент может отправить запрос, чтобы сервер использовал вместо текущего более новый протокол HTTP

HTTP-коды успешного выполнения запроса

HTTP-код Описание
200 OK

Сервер успешно обработал запрос, и клиент может получить запрашиваемый документ в теле ответа

201 Created Locatuion

Сервер успешно создал новый URL, заданный в HTTP-заголовке Locatuion

202 Accepted

Запрос принят сервером для обработки, но она еще не завершена

203 Non-Authoritative Information

Метаинформация в заголовке запроса не связана с данным сервером и скопирована с другого сервера

204 No Content

Выполнение запроса завершено, но никакой информации отправлять обратно не требуется. Клиент может продолжать просматривать текущий документ

205 Reset Content

Клиент должен сбросить текущий документ. Этот HTTP-заголовок можно использовать для сброса и удаления всех значений полей ввода в HTML-форме

206 Prtial Content

Сервер выполнил неполный запрос ресурса методом GET. Этот HTTP-код используется для ответа на запросы, содержащие HTTP-заголовок Range. Сервер отправляет HTTP-заголовок Content-Range, чтобы указать, какой сегмент данных приложен

300 Multiple Choices

Запрашиваемый ресурс соответствует набору документов. Сервер может отправить информацию о каждом документе с его собственным местоположением и информацией по согласованию содержимого, оставляя выбор на усмотрение клиента

301 Moved Permanently

Запрашиваемый ресурс на сервере отсутствует. Для переадресации клиента на новый URL отправляется HTTP-заголовок Locatuion. Все последующие запросы должны отправляться на новый URL

302 Moved Temporarily

Запрашиваемый ресурс временно перемещен. Для переадресации клиента на новый URL отправляется HTTP-заголовок Locatuion. В последующих запросах клиент может продолжать использовать старый URL

303 See Other

Запрашиваемый ресурс найден в другом месте, его местоположение уточняется сервером при помощи HTTP-заголовка Locatuion

304 Not Modified

Сервер использует этот HTTP-код в соответствии с HTTP-заголовком if-Modified-Since. Это означает, что запрашиваеьый документ не модефицировался с даты, определенной в HTTP-заголовке if-Modified-Since

305 Use Proxy

Для получения запрашиваемого ресурса клиент должен использовать прокси-сервер, адрес которого определяется сервером в HTTP-заголовке Locatuion

307 Temporary Redirect

Запрашиваемый ресурс временно перемещен в другое место. Для переадресации клиента на новый URL отправляется HTTP-заголовке Locatuion

HTTP-коды ошибочного запроса

HTTP-код Описание
400 Bad Request

В запросе клиента обнаружена синтаксическая ошибка

401 Unauthorized

Запрос требует аутентификации клиента. Для уточнения типа аутентификации и области запрашиваемого ресурса сервер отправляет HTTP-заголовок WWW-Authentificate

402 Payment Required

Данный HTTP-код зарезервирован для будущего использования в электронной коммерции

403 Forbidden

Доступ к запрашиваемому ресурсу запрещен. Клиент не должен повторять запрос.

404 Not Found

Запрашиваемый документ отсутствует на сервере

405 Method Not Allowed

Метод запроса, используемый клиентом, неприемлем. Сервер отправляет HTTP-заголовок Allow, в котором уточняются допустимые методы для получения доступа к запрашиваемому ресурсу

406 Not Acceptable

Запрашиваемый ресурс недоступен в том формате, который может принимать клиент (клиент обычно уточняет эти форматы в специальном HTTP-заголовке Accept). Если запрос не является запросом HEAD на получение лишь HTTP-заголовков с сервера без тела документа, то сервер может отправить заголовки Content-Language, Content-Encoding, Content-Type, чтобы определить, какие форматы являются доступными

407 Proxy Authentification Required

Несанкционированный запрос доступа к прокси-серверу: клиент должен аутентифицировать себя на прокси-сервере. Сервер отправляет HTTP-заголовок Proxy Authentificatе со схемой аутентификации и областью запрашиваемого ресурса

408 Request Time-Out

Клиент не завершил свой запрос за время ожидания запроса, заданное серверу,однако можетповторить запрос

409 Conflict

Возник конфликт запроса клиента с другим запросом. Вместе скодом состояния сервер может переслать информацию о типе конфликта

410 Gone

Запрашиваемый ресурс удаленен с сервера

411 Length Required

Клиент должен прислать в запросе HTTP-заголовок Content-Length

412 Precondition Filed

Если запрос клиента содежит один или более HTTP-заголовков if ..., сервер использует этот HTTP-код для оповещения, что одно или более условий, заданных в этих заголовках, не выполняются

413 Request Entity Too Large

Сервер отказывается выполнять запрос: слишком длинное тело сообщений

414 Request-URI Too Long

Сервер отказывается выполнять запрос: слишком длинный URI(URL)

415 Unsupported Media Type

Сервер отказывается выполнять запрос: отсутствует поддержка формата тела сообщения

417 Expectation Failed

Сервер не смог выполнить требования HTTP-заголовка Expect Request

HTTP-коды ошибочного запроса

HTTP-код Описание
500 Internal Server Error

Ошибка конфигурации сервера или внешней программы

501 Not Implemented

Сервер не поддерживает функции, требуемые для выполнения запроса

502 Bad Gateway

Неверный ответ вышестоящего сервера или прокси сервера

503 Servise Unavailable

Служба временно недоступна. С целью оповещения о времени открытия доступа к службе сервер может отправить заголовок Retry-After

504 Gateway Time-Out

Шлюз или прокси-сервер временно заблокирован

505 HTTP Version Not Supported

Не поддерживается используемая клиентом версия протокола HTTP

При работе HTTP-заголовками следует помнить, что они всегда предваряют содержимое страницы. Вывод любой информации (при помощи конструкции echo, функции print() или непосредственно вне тегов <?php и ?>) в окно браузера приводит к тому, что начинается отправка HTTP-документа. Согласно протоколу, HTTP-заголовки отправляются перед телом документа, и последующие попытки отправить дополнительные заголовки заканчиваются неудачей.

Перевод строки перед функцией header() блокирует ее работу

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<?php
header("Location: http://sevidi.narod.ru");
?>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Перевод строки перед функцией header() блокирует ее работу</title>
</head>

<body>
</body>
</html>

В окне веб-браузера это будет выглядеть ТАК.

В результате переадресация не осуществляется, а функция header() выводит предупреждение Warning: Cannot modify header information - headers already sent by (output started at D:\sevidi\373.php:2) in D:\sevidi\373.php on line 3, сообщающее, что отправка HTTP-заголовка невозможна, поскольку уже начата передача тела HTTP-документа. Иногда пробелы и переводы строк могут быть расположены внутри файлов, включаемых при помощи конструкций include() и require().

В ряде случаев нельзя быть заранее уверенным, отправлены HTTP-заголовки или все еще имеется возможность использовать функцию header(). Чтобы выяснить это, можно воспользоваться функцией headers_sent(), которая имеет следующий синтаксис:

dool headers_sent(&$file [, &$line])

Функция возвращает false, если HTTP-заголовки не были отправлены клиенту, и true — в противном случае. После отправки HTTP-заголовков функция при помощи необязательных аргументов $file и $line может сообщить, в каком файле и строке была начата передача тела HTTP-документа.

Использование функции headers_sent()

<?php
echo "Hello<br>";
if(!headers_sent($filename, $linenum))
{
header("Location: http://sevidi.narod.ru");
exit;
}
else
{
echo "Передача HTTP-документа начата в файле $filename в строке $linenum. Поэтому перенаправление на другой ресурс невозможно.";
exit;
}
?>

В окне веб-браузера это будет выглядеть ТАК.

Иногда бывает полезно проконтролировать, какие HTTP-заголовки были отправлены клиенту. Для этого удобно воспользоваться функцией headers_list(), которая имеет следующий синтаксис:

array headers_list()

Функция возвращает массив, содержащий отправленные клиенту HTTP-заголовки. Рассмотрим пример работы функции headers_list(); получаемый в результате ее работы массив для удобства восприятия выводится при помощи функции print_r() в тегах <pre> и </pre>, сохраняющих отступы и переводы строк.

Примечание. Клиенту отправляется произвольный HTTP-заголовок X-my-header со значение "Hello world". Нестандартные HTTP-заголовки, как правило, всегда предваряются префиксом Х-.

Использование функции headers_list()

<?php
header("X-my-header: Hello world!");
$arr=headers_list();
echo "<pre>";
print_r($arr);
echo "</pre>";
?>

В окне веб-браузера это будет выглядеть ТАК.

Скрипт выведет следующий дамп массива HTTP-заголовков:

Array  
(     
 [0] => X-Powered-By: PHP/5.2.8    
 [1] => X-my-header: Hello world!
 )  

Это не полный список HTTP-заголовков, которые получает клиент: это лишь те заголовки, которые отправляет РНР-скрипт. Помимо них клиент получает HTTP-заголовки, отправленные веб-сервером. Получить полный список HTTP-заголовков к странице можно при помощи сокетов.




  • Другие |
назадвверхвперед
Rambler's Top100