NexxDigital - компьютеры и операционные системы

В этой статье мы рассмотрим, для чего заголовки нужны, не вдаваясь в подробности, какой за что отвечает. Описание ролей самых распространённых заголовков будет дано в следующих статьях.

Все статьи из цикла:

  • Что такое Http заголовки. Общая теория.

HTTP расшифровывается как HyperText Transfer Protocol (протокол передачи гипертекста). Протокол — это набор правил, по которым разные устройства обмениваются данными. Он был создан в 1990-х годах. Сейчас он используется в сети интернет практически повсеместно. Всё, что вы видите в окне браузера, было получено посредством этого протокола. http заголовки — пожалуй главная вещь в общении между устройствами. Они передают основную информацию об устанавливающемся соединении и о передаваемой информации через это соединение.
Взглянем на схему общения двух устройств. Пусть этими устройствами будут ваш компьютер и какой-нибудь сервер в интернете:

Как видно, браузер отослал http-запрос. Он может выглядеть примерно так:

GET /other-19 HTTP/1.1 Host: www.scriptsite.ru User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ru,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive

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

Server: Apache/2.0.61 (Unix) mod_ssl/2.0.61 OpenSSL/0.9.8k mod_dp20/0.99.2 PHP/5.2.5 mod_python/3.3.1 Python/2.5.1 mod_ruby/1.2.6 Ruby/1.8.6(2007-09-24)

X-Powered-By: PHP/5.2.5

Set-Cookie: PHPSESSID=ft47gokfee6amv3eda3k1p93s3; path=/

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

Pragma: no-cache

Keep-Alive: timeout=10, max=1024

Connection: Keep-Alive

Transfer-Encoding: chunked

Content-Type: text/html

Первая строка — строка статуса. Остальные строки — заголовки. В схеме было показано, что подгружается ещё и содержимое страницы. Но это содержимое обычно не принято отображать в плагинах, просматривающих заголовки. Да и содержимое страницы — это только частный случай. По протоколу же не обязательно страница должна передаваться. Вместо неё могут быть переданы и картинка, и звуковой файл, и видео. И у всех них заголовки будут сильно отличаться.

Как увидеть http-заголовки?

Для того, чтобы увидеть http-заголовки, я рекомендую следующие плагины для браузера firefox:

Если вы пользуетесь браузером Chrome, просмотреть всю информацию можно, нажав на кнопку настройки — инструменты — инструменты разработчика. Вкладка networks.
Пользователям браузера opera ничего посоветовать не могу, так как не дружу с этим браузером. Установив плагины и запустив их, попробуйте обновить страницу. Вы сразу же увидите огромные списки запросов и ответов, посредством которых ваш браузер общался с сервером.

Http-заголовки и доступ к ним в php

Если вы являетесь php-разработчиком, вы можете получить доступ к заголовкам запроса с помощью функции getallheaders() . Для понимания её работы выполним такой код:

И мы получаем распечатку массива заголовков.

Но чаще к ним обращаются через глобальную переменную $_SERVER. Почти для каждого http заголовка есть аналогичное название элемента в этой переменной, образуемого по принципу HTTP_имя_заголовка. Так для того же ‘User_Agent’ есть переменная $_SERVER[‘HTTP_USER_AGENT’];

Для получения заголовков, которые сервер собирается отправить пользователю, используется функция headers_list() . Как правило, сервер составляет недостающие обязательные заголовки уже в конце работы всех скриптов. Поэтому этот массив будет содержать заголовки либо те, которые сервер создал перед началом выполнения скрипта (и они не будут изменены), либо те, которые мы установили вручную. Вручную их можно установить с помощью функции header(«текст заголовка»);
Выполним такой код:

Увидим распечатку готовых к отправке на момент вызова функции заголовков:

Первый заголовок был установлен автоматически, и он несёт в себе название сервера, на котором выполняется скрипт. Второй - установленный нами вручную. Если бы браузеру нужен был заголовок «Фрукт», он бы взял его из http-ответа сервра и использовал. Но так как наш браузер не нуждается в нём, то он просто игнорирует непонятную ему строку.

Структура http запроса

Наш запрос выглядит следующим образом:

Первая строка в нём, как уже было сказано раньше, является строкой запроса. Она состоит из трёх частей:

  • method (метод) — указывает, какого рода запрос. Самые распространённые методы: GET, POST, HEAD. О них будет написано в следующем параграфе.
  • path (путь) — как правило, это часть URL, идущая после домена. Например, если вы вводите в адресную строку http://www.scriptsite.ru/about/, значение path будет /about/.
  • protocol (протокол) — используемый протокол. Как правило, состоит из «HTTP» и версии протокола. Обычно, в современных браузерах используется версия 1.1

Дальше идут заголовки в виде строк формата «Имя: значение».
Кстати, данные о cookies также передаются в этом запросе в виде одного из заголовков. Большинство из этих строк не являются обязательными. Запрос может быть сокращён вообще до двух строк:

GET /article/show/4/ HTTP/1.1

Host: scriptsite.ru

Методы запроса

GET

get-запрос обычно используется для запроса документа с передачей некоторых параметров.
Это основной метод, используемый для получения html-страниц, изображений, CSS и JavaScript файлов, и т.д.
Из-за того, что параметры могут быть любыми, а на сервере нет ограничений по способам их обработки, часто метод для запросов данных используют для передачи информации. Например, у нас будет такая форма

При этом эти параметры будут видны в адресной строке браузера.

POST

Post — метод, используемый для отправки данных на сервер. Несмотря на то, что вы можете отправлять данные серверу методом GET через адресную строку браузера, в большинстве случаев предпочтительнее использовать POST. Отправлять большие объёмы данных через GET непрактично. К тому же GET имеет некоторые ограничения, не позволяющие, например, опубликовать эту статью на моём сайте через одну лишь строку браузера. POST запросы чаще всего используются для передачи web-форм. Давайте изменим форму из предыдущего примера, задав ей метод POST

Заголовки Content-Type и Content-Lenght добавлены автоматически. Они содержат информацию о типе и размере данных.
Все данные передаются после отправки заголовков в таком же виде, как в строке запроса GET

Метод POST повсеместно используется в AJAX, cURL, и т.д.
Формы загрузки файлов работают только через метод POST

HEAD

Многие из вас могли и не знать об этом типе запросов.
Этот метод работает аналогично post, только сервер не возвращает никакого дополнительного содержимого, кроме заголовков.
Использование этого заголовка бывает оправдано во многих случаях. Например, когда браузер когда-то закешировал файл, а теперь хочет узнать, не изменился ли тот на сервере. Браузер может запросить информацию о нём, не скачивая сам файл полностью.
Кроме того, этот метод часто используется в сервисах, проверяющих ссылки на работоспособность. Он позволяет узнавать, по каким URL адресам ещё есть файлы, а по каким их уже нет, при этом опять же файлы не скачиваются.

Структура http ответа

Сервер отвечает на каждый запрос такими ответами:

Первая строка — версия протокола.
Далее указывается код статуса сервера. В данном значение кода равно 200. Код статуса показывает браузеру, что именно произошло на сервере во время обработки запроса. 200й статус означает, что наш запрос был успешно обработан, и сервер отправит запрашиваемый документ сразу после передачи заголовков.
В остальных строчках указывается всевозможная информация о передаваемом файле.

К информации о статусах можно ещё добавить факт об ошибке 404. Её название пошло именно из кода 404, который отсылает сервер, когда не может найти файл на своих дисках.
Более подробно о статусах сервера написано в следующей статье.

Обратите также внимание

Формат ответа очень похож на формат запроса: он также имеет заголовок и тело, разделенное пустой строкой.

Заголовок также состоит из основной строки и строк параметров, но формат основной строки отличается от таковой в заголовке запроса.

Основная строка запроса состоит из 3-х полей, разделенных пробелами:

Версия протокола - аналогичен соответствующему параметру запроса.

Код ошибки - кодовое обозначение "успешности" выполнения запроса. Код 200 означает "все нормально" (OK).

Словесное описание ошибки - "расшифровка" предыдущего кода. Например для 200 это OK, для 500 - Internal Server Error.

Наиболее употребительные параметры http-ответа:

Connection - аналогичен соответствующему параметру запроса.
Если сервер не поддерживает Keep-Alive (есть и такие), то значение Connection в ответе всегда close.

Поэтому, на мой взгляд, правильной тактикой браузера является следующая:
1. выдать в запросе Connection: Keep-Alive;
2. о состоянии соединения судить по полю Connection в ответе.

Content-Type ("тип содержимого") - содержит обозначение типа содержимого ответа.

В зависимости от значения Content-Type браузер воспринимает ответ как HTML-страницу, картинку gif или jpeg, как файл, который надо сохранить на диске, или как что-либо еще и предпринимает соответствующие действия. Значение Content-Type для браузера аналогично значению расширения файла для Windows.

Некоторые типы содержимого:

text/html - текст в формате HTML (веб-страница);
text/plain - простой текст (аналогичен "блокнотовскому");
image/jpeg - картинка в формате JPEG;
image/gif - то же, в формате GIF;
application/octet-stream - поток "октетов" (т.е. просто байт) для записи на диск.

На самом деле типов содержимого гораздо больше.

Content-Length ("длина содержимого") - длина содержимого ответа в байтах.

Last-Modified ("Модифицирован в последний раз") - дата последнего изменения документа.

HTTP запрос, или сообщение состоит из трех частей: строки запроса, и тела HTTP сообщения.

Строка запроса , или стартовая строка: в запросе к серверу — строка, которая содержит тип запроса (метод), URI запрашиваемой страницы, и версия (например HTTP/1.1). В ответе от сервера эта строка содержит версию HTTP протокола, и код ответа. Код ответа представляет собой целое число из трех цифр. За ним обычно следует отделённая пробелом поясняющая фраза, поясняющая код, например: 200 OK, или 404 Not Found.

Методы (типы) HTTP запроса : GET, POST, PUT, PATCH, HEAD, DELETE, TRACE. Чаще всего в HTTP запросе используются методы GET, или POST: GET — используется для запроса содержимого web-страницы по указанному URI. URI — это адрес страницы без указания , например: /internet/chto-takoe-http-zapros-soobshhenie/ вместо сайт/internet/chto-takoe-http-zapros-soobshhenie/. Браузер может передавать параметры в GET в URI после символа « ? »: GET /index.php?param1=value1¶m2=value2. Кроме обычного метода GET, различают ещё условный GET и частичный GET. Условные запросы GET содержат заголовки If-Modified-Since , If-Match , If-Range и подобные.

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

— это часть запроса, в котором содержатся различные параметры, которые используются для правильного построения web-страницы.

Тело HTTP сообщения — содержит полученные от сервера данные, например сформированную web-страницу в виде HTML кода, либо ресурс, например картинку.

Пример HTTP сообщений:

HTTP запрос к серверу:

GET /internet/chto-takoe-http-zapros-soobshhenie/ HTTP/1..9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2150.0 Accept-Encoding: gzip, deflate, sdch Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: wp-settings-1=hidetb%3D; wp-settings-time-1=1424958215; wordpress_test_cookie=WP+Cookie;

Ответ от сервера:

HTTP/1.1 200 OK - стартовая строка ответа : Server: nginx/1.6.2 Date: Sun, 19 Apr 2015 00:22:50 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 9431 Connection: keep-alive Keep-Alive: timeout=30 X-Powered-By: PHP/5.5.22 Expires: Wed, 11 Jan 1984 05:00:00 GMT Cache-Control: no-cache, must-revalidate, max-age=0 Pragma: no-cache Vary: Accept-Encoding Content-Encoding: gzip Далее следует тело ответа (страница в HTML).

1. Протокол HTTP. Введение

Сразу хочу уточнить одну маленькую вещь. Страшное слово протокол есть не что иное, как соглашение множества людей, просто в один прекрасный момент люди решили: "Давайте будем делать так, и тогда все будет в порядке". Бояться нечего, все просто до безобразия и это безобразие мы сейчас будем вскрывать. Итак, что же это такое протокол HTTP и с чем его едят?

1.1 Клиент и сервер

Чудес в мире, а тем более в мире программизма и интернета не бывает! Усвойте это как незыблемую истину. И, если программа не работает или работает не так как хочется, то, значит, скорее всего, она либо написана не правильно, либо содержит ошибки. Итак, как же все-таки браузер просит сервер прислать ему хоть что-нибудь? Да очень просто! Надо только немного расслабиться и начать получать удовольствие от процесса:-)

1.2. Пишем наш первый HTTP запрос

Если Вы думаете, что все слишком сложно, то Вы ошибаетесь. Человек так устроен, что просто не способен создавать что-то сложное, иначе он сам в этом запутается:-) Итак, есть браузер и есть Web-сервер. Инициатором обмена данными всегда выступает браузер. Web-сервер никому, никогда просто так ничего не пошлет, чтобы он что-нибудь отправил браузеру - надо, чтобы браузер об этом попросил. Простейший HTTP запрос моет выглядеть, например, так:


GET http : //www.php.net/ HTTP/1.0rnrn


* GET (В переводе с английского означает "получить") - тип запроса, тип запроса может быть разным, например POST, HEAD, PUT, DELETE (часть из них мы рассмотрим ниже).
* http://www.php.net/ - URI (адрес) от которого мы хотим получить хоть какую-нибудь информацию (естественно мы надеемся подучить HTML страницу).
* HTTP/1.0 - тип и версия протокола, который мы будем использовать в процессе общения с сервером.
* rn - конец строки, который необходимо повторить два раза, зачем, станет понятно немного позднее.

Вы можете выполнить данный запрос очень просто. Запустите программу telnet.exe, введите в качестве хоста www.php.net, укажите порт 80, и просто наберите данный запрос, нажав два раза Enter в качестве rnrn. В ответ вы получите HTML код главной страницы сайта www.php.net.

1.3 Структура запроса

Рассмотрим, из чего состоит HTTP запрос. Все достаточно просто. Начнем с того, что HTTP запрос - это вполне осмысленный текст. Из чего же он состоит в общем случае? Будем рассматривать протокол HTTP 1.0. Итак :


Request - Line [ General - Header | Request - Header | Entity - Header ] rn [ Entity - Body ]


* Request-Line - строка запроса
*

Формат : "Method Request-URI HTTP-Versionrn"
* Method -
метод , которым будет обрабатываться ресурс Request-URI, может быть GET, POST, PUT, DELETE или HEAD.
* Request-URI - относительная или абсолютная ссылка на страницу с набором параметров, например, /index.html или http://www.myhost.ru/index.html или /index.html?a=1&b=qq. В последнем случае серверу будет передан запрос с набором переменных a и b с соответствующими значениями, а знак "&" - амперсант служит разделителем между параметрами.
* HTTP-Version - версия HTTP протокола, в нашем случае "HTTP/1.0".

Нам крайне интересны методы обработки GET и POST. Методом GET можно просто передать параметры в скрипт, а методом POST можно эмулировать submit формы.

Для метода GET, Request-URI может выглядеть, например, так: "/index.html?param1=1¶m2=2".

* General-Header - главная часть заголовка.
Формат:
Может иметь только два параметра: Date или Pragma. Date - дата по Гринвичу в формате "День недели, Число Месяц Год ЧЧ:ММ:СС GMT", например, "Tue, 15 Nov 1994 08:12:31 GMT" - дата создания запроса. Pragma может иметь одно значение no-cache, которое запрещает кэширование страницы.

* Request-Header - часть заголовка , описывающая запрос .

Request-Header может иметь следующие параметры : Allow, Authorization, From, If-Modified-Since, Referer, User-Agent.
В данной главе мы не будем рассматривать параметр Autorization, так как он используется для доступа к закрытым ресурсам, что требуется не так уж часто. Вы можете самостоятельно изучить формирование заголовка для авторизованного доступа на сайте www.w3c.org.

* Allow - задает допустимые методы обработки.
Формат: "Allow: GET | HEADn".
Параметр игнорируется при указании метода обработки POST в Request-Line. Задает допустимые методы обработки запроса. Прокси сервера не модифицируют параметр Allow и он в неизменном виде доходит до сервера.

* From - e-mail адрес, пославшего запрос.
Формат: "From: adderssrn".
Например, "From: [email protected]".

* If-Modified-Since - указывает, что запрос не модифицировался с такого-то времени.
Формат: "If-Modified-Since: datern"
Используется только для метода обработки GET. Дата указывается по Гринвичу в таком же формате, как и для параметра Date в General-Header.

* Referrer - абсолютная ссылка на страницу, с которой произошла инициация запроса, т. е. ссылка на страницу, с которой пользователь перешел на нашу.
Формат: "Referrer: urln".
Пример: "Referrer: www.host.ru/index.htmln".
* User-Agent - тип браузера.
Например: "User-Agent: Mozilla/4.0n"

* Entity-Header - часть заголовка, описывающая данные Entity-Body.
В данной части запроса задаются параметры, которые описывают тело страницы. Entity-Header может содержать следующие параметры: Allow, Content-Encoding, Content-Length, Content-Type, Expires, Last-Modified, extension-header.

* Allow - параметр аналогичный Allow из General-Header.

* Content-Encoding - тип кодирования данных Entity-Body.
Формат: "Сontent-Encoding: x-gzip | x-compress | другой типn".
Пример: "Сontent-Encoding: x-gzipn". Символ "|" означает слово "или", то есть то или то или то и.т.д.
Другой тип может указывать на способ кодирования данных, например, для метода POST: "Сontent-Encoding: application/x-www-form-urlencodedn".

* Content-Length - количество байт, пересылаемых в Entity-Body. Значение Content-Length имеет совсем другой смысл для данных, пересылаемых в формате MIME, где он выступает как параметр описания части данных - "external/entity-body". Допустимыми являются целые числа от нуля и больше.
Пример: "Content-Length: 26457n".

* Content-Type - тип передаваемых данных.
Например: "Content-Type: text/htmln".

* Expires - Время, когда страница должна быть удалена из кэша браузера.
Формат: "Expires: daten". Формат даты алогичен формату даты для параметра Date из General-Header.

* Last-Modified - время последнего изменения пересылаемых данных.
Формат: "Last-Modified: daten". Формат даты алогичен формату даты для параметра Date из General-Header.

* Extention-header - часть заголовка, которая может предназначаться, например, для обработки браузером, или другой программой, которая принимает документ. В данной части можно описывать свои параметры в формате "ParameterName: parametervaluen". Данные параметры будут игнорироваться, если программа-клиент не знает, как их обработать.
Например: "Cookie: r=1rn" - устанавливает всем известные печеньки для страницы.

А теперь после таких страшных слов давайте попробуем немного успокоиться и понять, что же нам надо? Понимать мы естественно будем на примерах.

Давайте представим, что нам надо получить страницу с сайта, передав Cookies (Печеньки), иначе нас просто пошлют как незванных гостей, и более того, известно, что на данную страницу пускают только после того, как Вы побывали на главной странице сайта.

2 Метод GET

Напишем наш запрос.


GET http :
Host : www . site . rurn

Cookie : income = 1rn
rn


Данный запрос говорит нам о том, что мы хотим получить содержимое страницы по адресу http://www.site.ru/news.html, использую метод GET. Поле Host говорит о том, что данная страница находится на сервере www.site.ru, поле Referer говорит о том, что за новостями мы пришли с главной страницы сайта, а поле Cookie говорит о том, что нам была присвоена такая-то кука. Почему так важны поля Host, Referer и Сookie? Потому что нормальные программисты при создании динамических сайтов проверяют данные поля, которые появляются в скриптах (РНР в том числе) в виде переменных. Для чего это надо? Для того, например, чтобы сайт не грабили, т.е. не натравливали на него программу для автоматического скачивания, или для того, чтобы зашедший на сайт человек всегда попадал бы на него только с главной страницы и.т.д.

Теперь давайте представим, что нам надо заполнить поля формы на странице и отправить запрос из формы, пусть в данной форме будет два поля: login и password (логин и пароль),- и, мы естественно знаем логин и пароль.


GET http : //www.site.ru/news.html?login=Petya%20Vasechkin&password=qq HTTP/1.0rn
Host : www . site . rurn
Referer : http : //www.site.ru/index.htmlrn
Cookie : income = 1rn
rn


Логин у нас "Petya Vasechkin" Почему же мы должны писать Petya%20Vasechkin? Это из=за того, что специальные символы могут быть распознаны сервером, как признаки наличия нового параметра или конца запроса и.т.д. Поэтому существует алгоритм кодирования имен параметров и их значений, во избежание оштбочных ситуаций в запросе. Полное описание данного алгоритма можно найти здесь, а в PHP есть функции rawurlencode и rawurldecode для кодирования и декодирования соответственно. Хочу отметеить, что декодирование РНР делает сам, если в запросе были переданы закодированные параметры. На этом я закону первую главу знакомства c протоколом HTTP. В следуючей главе мы рассмотрим построение запросов типа POST (в переводе с английского - "отправить"), что будет гораздо интереснее, т.к. именно данный тип запросов используется при отправке данных из HTML форм.

3. Метод POST.

В случае HTTP запроса типа POST существует два варианта передачи полей из HTML форм, а именно, используя алгоритм application/x-www-form-urlencoded и multipart/form-data. Различия между данными алгоритмами весьма существенные. Дело в том, что алгоритм первого типа создавался давным-давно, когда в языке HTML еще не предусматривали возможность передачи файлов через HTML формы. Итак, давайте рассмотрим эти алгоритмы на примерах.

3.1 Content-Type: application/x-www-form-urlencoded.

Пишем запрос, аналогичный нашему запросу GET для передачи логина и пароля, который был рассмотрен в предыдущей главе:


POST http : //www.site.ru/news.html HTTP/1.0rn
Host : www . site . rurn
Referer : http : //www.site.ru/index.htmlrn
Cookie : income = 1rn
Content - Type : application / x - www - form - urlencodedrn
Content - Length : 35rn
rn


Здесь мы видим пример использования Content-Type и Content-Length полей заголовка. Content-Length говорит, сколько байт будет занимать область данных, которая отделяется от заголовка еще одним переводом строки rn. А вот параметры, которые раньше для запроса GET помещались в Request-URI, теперь находятся в Entity-Body. Видно, что они формируются точно также, просто надо написать их после заголовка. Хочу отметить еще один важный момент, ничто не мешает, одновременно с набором параметров в Entity-Body, помещать параметры с другими именами в Request-URI, например:


POST http : //www.site.ru/news.html?type=user HTTP/1.0rn
.....
rn
login = Petya % 20Vasechkin & password = qq


3.2 Content-Type: multipart/form-data

Как только интернет мир понял, что неплохо бы было через формы отсылать еще и файлы, так W3C консорциум взялся за доработку формата POST запроса. К тому времени уже достаточно широко применялся формат MIME (Multipurpose Internet Mail Extensions - многоцелевые расширения протокола для формирования Mail сообщений), поэтому, чтобы не изобретать велосипед заново, решили использовать часть данного формата формирования сообщений для создания POST запросов в протоколе HTTP.

Каковы же основные отличия этого формата от типа application/x-www-form-urlencoded?

Главное отличие в том, что Entity-Body теперь можно поделить на разделы, которые разделяются границами (boundary). Что самое интересное - каждый раздел может иметь свой собственный заголовок для описания данных, которые в нем хранятся, т.е. в одном запросе можно передавать данные различных типов (как в Mail письме Вы одновременно с текстом можете передавать файлы).

Итак, приступим. Рассмотрим опять все тот же пример с передачей логина и пароля, но теперь в новом формате.


POST http : //www.site.ru/news.html HTTP/1.0rn
Host : www . site . rurn
Referer : http : //www.site.ru/index.htmlrn
Cookie : income = 1rn

Content - Length : 209rn
rn
-- 1BEF0A57BE110FD467Arn
Content - Disposition : form - data ; name = "login" rn
rn
Petya Vasechkinrn
-- 1BEF0A57BE110FD467Arn
Content - Disposition : form - data ; name = "password" rn
rn
qqrn
-- 1BEF0A57BE110FD467A -- rn


Теперь давайте разбираться в том что написано. :-) Я специально выделил некоторые символы rn жирным, чтобы они не сливались с данными. Присмотревшись внимательно можно заметить поле boundary после Content-Type. Это поле задает разделитель разделов - границу. В качестве границы может быть использована строка, состоящая из латинских букв и цифр, а так же из еще некоторых символов (к сожалению, не помню каких еще). В теле запроса в начало границы добавляется "--", а заканчивается запрос - границей, к которой символы "--" добавляются еще и в конец. В нашем запросе два раздела, первый описывает поле login, а второй поле password. Content-Disposition (тип данных в разделе) говорит, что это будут данные из формы, а в поле name задается имя поля. На этом заголовок раздела заканчивается и далее следует область данных раздела, в котором помещается значение поля (кодировать значение не требуется!).

Хочу обратить Ваше внимание та то, что в заголовках разделов не надо использовать Content-Length, а вот в заголовке запроса надо и его значение является размером всего Entity-Body, стоящего после второго rn, следующего за Content-Length: 209rn. Т.е. Entity-Body отделяется от заголовка дополнительным переводом строки (что можно заметить и в разделах).

А теперь давайте напишем запрос для передачи файла.


POST http : //www.site.ru/postnews.html HTTP/1.0rn
Host : www . site . rurn
Referer : http : //www.site.ru/news.htmlrn
Cookie : income = 1rn
Content - Type : multipart / form - data ; boundary = 1BEF0A57BE110FD467Arn
Content - Length : 491rn
rn
-- 1BEF0A57BE110FD467Arn
Content - Disposition : form - data ; name = "news_header" rn
rn
Пример новостиrn
-- 1BEF0A57BE110FD467Arn
Content - Disposition : form - data ; name = "news_file" ; filename = "news.txt" rn
Content - Type : application / octet - streamrn
Content - Transfer - Encoding : binaryrn
rn
А вот такая новость , которая лежит в файле news . txtrn
-- 1BEF0A57BE110FD467A -- rn


В данном примере в первом разделе пересылается заголовок новости, а во втором разделе пересылается файл news.txt. Внимательный да увидит поля filename и Content-Type во втором разделе. Поле filename задает имя пересылаемого файла, а поле Content-Type - тип данного файла. Application/octet-stream говорит о том, что это стандартный поток данных, а Content-Transfer-Encoding: binary говорит на о том, что это бинарные данные, ничем не закодированные.

Очень важный момент. Большинство CGI скриптов написано умными людьми, поэтому они любят проверять тип пришедшего файла, который стоит в Content-Type. Зачем? Чаще всего закачка файлов на сайтах используется для получения картинок от посетителя. Так вот, браузер сам пытается определить что за файл посетитель хочет отправить и вставляет соответствующий Content-Type в запрос. Скрипт его проверяет при получении, и, например, если это не gif или не jpeg игнорирует данный файл. Поэтому при "ручном" формировании запроса позаботьтесь о значении Content-Type, чтобы оно было наиболее близким к формату передаваемого файла.

Image/gif для gif
image/jpeg для jpeg
image/png для png
image/tiff для tiff (что используется крайне редко, уж больно емкий формат)

В нашем примере формируется запрос, в котором передается текстовый файл. Точно так же формируется запрос для передачи бинарного файла.

4. Постскриптум.

Думаю, что о передаче запросов на сервер не стоит рассказывать подробно. Это уже дело чисто РНР техники:-). Достаточно внимательно прочитать раздел о функциях работы с сокетами, или о функциях модуля CURL в официальной документации РНР.

Из выше сказанного, надеюсь теперь понятно, почему вопрос: "Как мне сформировать POST запрос, используя функцию header?" - бессмысленен. Функция header(string) добавляет запись только в заголовок запроса, но никак не в тело запроса.

Назад
HTTP . В его основу положено взаимодействие " клиент-сервер ", то есть предполагается, что:
  1. Потребитель- клиент инициировав соединение с поставщиком-сервером посылает ему запрос;
  2. Поставщик- сервер , получив запрос, производит необходимые действия и возвращает обратно клиенту ответ с результатом.

    При этом возможны два способа организации работы компьютера-клиента:

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

Прежде чем перейти к конкретным клиент-серверным веб-технологиям, рассмотрим основные принципы и структуру базового протокола HTTP .

Протокол HTTP

HTTP (HyperText Transfer Protocol - RFC 1945, RFC 2616) - протокол прикладного уровня для передачи гипертекста.

Центральным объектом в HTTP является ресурс , на который указывает URL в запросе клиента. Обычно такими ресурсами являются хранящиеся на сервере файлы. Особенностью протокола HTTP является возможность указать в запросе и ответе способ представления одного и того же ресурса по различным параметрам: формату, кодировке, языку и т. д. Именно благодаря возможности указания способа кодирования сообщения клиент и сервер могут обмениваться двоичными данными, хотя изначально данный протокол предназначен для передачи символьной информации. На первый взгляд это может показаться излишней тратой ресурсов. Действительно, данные в символьном виде занимают больше памяти, сообщения создают дополнительную нагрузку на каналы связи, однако подобный формат имеет много преимуществ. Сообщения, передаваемые по сети, удобочитаемы, и, проанализировав полученные данные, системный администратор может легко найти ошибку и устранить ее. При необходимости роль одного из взаимодействующих приложений может выполнять человек, вручную вводя сообщения в требуемом формате.

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

Все программное обеспечение для работы с протоколом HTTP разделяется на три основные категории:

  • Серверы - поставщики услуг хранения и обработки информации (обработка запросов).
  • Клиенты - конечные потребители услуг сервера (отправка запросов).
  • Прокси-серверы для поддержки работы транспортных служб.

Основными клиентами являются браузеры , например: Internet Explorer, Opera, Mozilla Firefox, Netscape Navigator и другие. Наиболее популярными реализациями веб-серверов являются: Internet Information Services ( IIS ), Apache, lighttpd, nginx. Наиболее известные реализации прокси-серверов: Squid, UserGate, Multiproxy, Naviscope.

"Классическая" схема HTTP -сеанса выглядит так.

  1. Установление TCP-соединения.
  2. Запрос клиента.
  3. Ответ сервера.
  4. Разрыв TCP-соединения.

Таким образом, клиент посылает серверу запрос , получает от него ответ, после чего взаимодействие прекращается. Обычно запрос клиента представляет собой требование передать HTML -документ или какой-нибудь другой ресурс , а ответ сервера содержит код этого ресурса.

В состав HTTP -запроса, передаваемого клиентом серверу, входят следующие компоненты.

  • Строка состояния (иногда для ее обозначения используют также термины строка-статус, или строка запроса).
  • Поля заголовка.
  • Пустая строка.
  • Тело запроса.

Строку состояния вместе с полями заголовка иногда называют также заголовком запроса .


Рис. 2.1.

Строка состояния имеет следующий формат:

метод_запроса URL_pecypca версия_протокола_НТТР

Рассмотрим компоненты строки состояния, при этом особое внимание уделим методам запроса.

Метод , указанный в строке состояния, определяет способ воздействия на ресурс , URL которого задан в той же строке. Метод может принимать значения GET , POST , HEAD , PUT , DELETE и т.д. Несмотря на обилие методов, для веб-программиста по-настоящему важны лишь два из них: GET и POST .

  • GET . Согласно формальному определению, метод GET предназначается для получения ресурса с указанным URL. Получив запрос GET , сервер должен прочитать указанный ресурс и включить код ресурса в состав ответа клиенту. Ресурс, URL которого передается в составе запроса, не обязательно должен представлять собой HTML-страницу, файл с изображением или другие данные. URL ресурса может указывать на исполняемый код программы, который, при соблюдении определенных условий, должен быть запущен на сервере. В этом случае клиенту возвращается не код программы, а данные, сгенерированные в процессе ее выполнения. Несмотря на то что, по определению, метод GET предназначен для получения информации, он может применяться и в других целях. Метод GET вполне подходит для передачи небольших фрагментов данных на сервер.
  • POST . Согласно тому же формальному определению, основное назначение метода POST - передача данных на сервер. Однако, подобно методу GET , метод POST может применяться по-разному и нередко используется для получения информации с сервера. Как и в случае с методом GET , URL, заданный в строке состояния, указывает на конкретный ресурс. Метод POST также может использоваться для запуска процесса.
  • Методы HEAD и PUT являются модификациями методов GET и POST.

Версия протокола HTTP , как правило, задается в следующем формате:

HTTP/версия.модификация

Поля заголовка , следующие за строкой состояния, позволяют уточнять запрос , т.е. передавать серверу дополнительную информацию. Поле заголовка имеет следующий формат:

Имя_поля: Значение

Назначение поля определяется его именем, которое отделяется от значения двоеточием.

Имена некоторых наиболее часто встречающихся в запросе клиента полей заголовка и их назначение приведены в таблице 2.1 .

Таблица 2.1. Поля заголовка запроса HTTP.
Поля заголовка HTTP -запроса Значение
Host Доменное имя или IP-адрес узла, к которому обращается клиент
Referer URL документа, который ссылается на ресурс, указанный в строке состояния
From Адрес электронной почты пользователя, работающего с клиентом
Accept MIME-типы данных, обрабатываемых клиентом. Это поле может иметь несколько значений, отделяемых одно от другого запятыми. Часто поле заголовка Accept используется для того, чтобы сообщить серверу о том, какие типы графических файлов поддерживает клиент
Accept-Language Набор двухсимвольных идентификаторов, разделенных запятыми, которые обозначают языки, поддерживаемые клиентом
Accept-Charset Перечень поддерживаемых наборов символов
Content-Type MIME-тип данных, содержащихся в теле запроса (если запрос не состоит из одного заголовка)
Content-Length Число символов, содержащихся в теле запроса (если запрос не состоит из одного заголовка)
Range Присутствует в том случае, если клиент запрашивает не весь документ, а лишь его часть
Connection Используется для управления TCP-соединением. Если в поле содержится Close, это означает, что после обработки запроса сервер должен закрыть соединение. Значение Keep-Alive предлагает не закрывать TCP-соединение, чтобы оно могло быть использовано для последующих запросов
User-Agent Информация о клиенте

Во многих случаях при работе в Веб тело запроса отсутствует. При запуске CGI-сценариев данные, передаваемые для них в запросе, могут размещаться в теле запроса.



Если заметили ошибку, выделите фрагмент текста и нажмите Ctrl+Enter
ПОДЕЛИТЬСЯ:
NexxDigital - компьютеры и операционные системы