Протокол — это набор синтаксических и сематических правил, использующихся при обмене данных между двумя компьютерами, который определяет команды, их синтаксис и порядок отправки, а также очередность отправки команд. Хотя протоколов взаимодействия очень много, веб-разработчики в основном имеют дело с прикладными протоколами и в первую очередь с HTTP-протоколом, который служит для обмена информацией между веб-сервером и браузером (клиентом).
Примечание. Все стандарты в сети Иртернет оформляются в виде RFC-документов; так протокол HTTP описывается главным образом в RFC2616. Ссылки на него можно получить при помощи любой любой поисковой системы.
Работа протокола HTTP не сводится только к передаче сервером HTML-документа по запросу клиента. Помимо HTML-документа, файла или изображения браузер и сервер обмениваются HTTP-заголовками, через которые клиент может сообщить о своих предпочтениях, типе и версии браузера и операционной системы. Сервер, в свою очередь, может сообщить клиенту об ошибочном запросе, "попросить" его установить cookie и т.п. Язык разметки HTML и серверный язык РНР разрабатывались таким образом, чтобы разработчик мог работать без знания HTTP — это позволит отделить уровни протокола и веб-приложения друг от друга. Тем не менее, совершенно абстрагироваться от протокола HTTP не удается, так как его использование зачастую позволяет более гибко управлять работой веб-приложения. В связи с этим в РНР введено несколько инструментов управления протоколом HTTP, которые будут обсуждаться далее в этом разделе:
- функции для работы с HTTP-заголовками;
- функции для установки сессий и cookie;
- сокеты;
- библиотека CURL.
Помимо этого, будет рассмотрен смежный вопрос преобразования IP-адресов и доменных имен.
Функции для работы с HTTP-заголовками
В ответ на запрос серверу, клиент получает HTTP-документ,который состоит из HTTP-заголовков и тела документа, содержащего HTML-страницу или изображение. HTTP-заголовки, как правило, формируются сервером автоматически и в большинстве случаев веб-разработчику нет надобности отправлятьих в ручную. Впрочем, последнее справедливо только для РНР, тогда как, например, при создании GGI-программы припомощи Perl или С разработчик вынужден самостоятельно реализовывать эту часть 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://rambler.ru");
?>
Механизм HTTP-заголовков дублирован в языке разметки HTTP и добиться схожего поведения можно при помощи передачи HTTP-заголовка через META-тег.
Переадресация средствами HTML
<META http-equiv="refresh" content="0; URL=http://rambler.ru">
Если в качестве второго параметра передать функции header()
значение true
, то все предыдущие HTTP-заголовки с таким же именем будут заменяться последующими.
Переадресация на сайт https://sevidi.ru
<?php
header("Location: http://www.softtime.ru", true);
header("Location: http://sevidi.ru", true);
?>
На каждый запрос клиента сервер может возвращать HTTP-код состояния, отражающий вид переадресации при окончательном или временном перемещении документа. Если документ найден и успешно отправлен клиенту, в HTTP-заголовки помещается код состояния 200; если документ не найден — 404; в случае переадресации, клиенту отправляется код состояния 302 — "ресурс временно перемещен". Иногда бывает полезно изменить код состояния на 301 — "ресурс перемещен постоянно".
Изменение состояния кода
<?php
header("Location: http://sevidi.narod.ru", true);
header ("HTTP/1.1 301 Moved Remanently");
?>
Коды состояния разделяются на классы, каждый из которых начинается с новой сотни:
- 100—199 — информационные коды состояния, сообщающие клиенту, что сервер пребывает в процессе обработки запроса. Реакция клиента на данные коды не требуется;
- 200—299 — коды успешного выполнения запроса. Получение данного кода ответа на запрос означает, что запрос успешно выполнен и в теле присланного документа находится запрашиваемый документ, который можно передать пользователю;
- 300—399 — коды переадресации, предназначенные для уведомления клиента о том, что для завершения запроса необходимо выполнить дальнейшие действия (как правило, перейти по новому адресу);
- 400—499 — коды ошибочного запроса, отправляемые клиенту, если сервер не может обработать его запрос;
- 500—599 — коды ошибок сервера, возникающих по вине сервера (как правило, из-за синтаксической ошибки в файле .htaccess).
Не все коды состояния имеют смысл; часть из них зарезервирована для дальнейших расширений. В таблицах ниже, описываются коды состояния для протокола HTTP 1.1, используемого в настоящее время для распространения HTTP-страниц в сети Интернет.
HTTP-код | Описание |
---|---|
100 Continue | Сервер готов получить оставшуюся часть запроса |
101 Switching Protocols | Сервер готов переключить протокол приложения на протокол, указанный в заголовке запроса Upgrade, предоставленного клиентом. Переключение должно выполняться, только если указанный протокол имеет преимущество над старым, например, клиент может отправить запрос, чтобы сервер использовал вместо текущего более новый протокол 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-код | Описание |
---|---|
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-код | Описание |
---|---|
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-заголовков к странице можно при помощи сокетов.
Комментарии(0)
Для добавления комментариев надо войти в систему и авторизоватьсяКомментирование статей доступно только для зарегистрированных пользователей:Зарегистрироваться