Скачиваний:
100
Добавлен:
09.05.2014
Размер:
601.5 Кб
Скачать

2 Метод get

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

GET http://www.site.ru/news.html HTTP/1.0\r\n

Host: www.site.ru\r\n

Referer: http://www.site.ru/index.html\r\n

Cookie: income=1\r\n

\r\n

Данный запрос говорит нам о том, что мы хотим получить содержимое страницы по адресу 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.0\r\n

Host: www.site.ru\r\n

Referer: http://www.site.ru/index.html\r\n

Cookie: income=1\r\n

\r\n

Логин у нас "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.0\r\n

Host: www.site.ru\r\n

Referer: http://www.site.ru/index.html\r\n

Cookie: income=1\r\n

Content-Type: application/x-www-form-urlencoded\r\n

Content-Length: 35\r\n

\r\n

login=Petya%20Vasechkin&password=qq

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

POST http://www.site.ru/news.html?type=user HTTP/1.0\r\n

.....

\r\n

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.0\r\n

Host: www.site.ru\r\n

Referer: http://www.site.ru/index.html\r\n

Cookie: income=1\r\n

Content-Type: multipart/form-data; boundary=1BEF0A57BE110FD467A\r\n

Content-Length: 209\r\n

\r\n

--1BEF0A57BE110FD467A\r\n

Content-Disposition: form-data; name="login"\r\n

\r\n

Petya Vasechkin\r\n

--1BEF0A57BE110FD467A\r\n

Content-Disposition: form-data; name="password"\r\n

\r\n

qq\r\n

--1BEF0A57BE110FD467A--\r\n

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

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

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

POST http://www.site.ru/postnews.html HTTP/1.0\r\n

Host: www.site.ru\r\n

Referer: http://www.site.ru/news.html\r\n

Cookie: income=1\r\n

Content-Type: multipart/form-data; boundary=1BEF0A57BE110FD467A\r\n

Content-Length: 491\r\n

\r\n

--1BEF0A57BE110FD467A\r\n

Content-Disposition: form-data; name="news_header"\r\n

\r\n

Пример новости\r\n

--1BEF0A57BE110FD467A\r\n

Content-Disposition: form-data; name="news_file"; filename="news.txt"\r\n

Content-Type: application/octet-stream\r\n

Content-Transfer-Encoding: binary\r\n

\r\n

А вот такая новость, которая лежит в файле news.txt\r\n

--1BEF0A57BE110FD467A--\r\n

В данном примере в первом разделе пересылается заголовок новости, а во втором разделе пересылается файл 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 (что используется крайне редко, уж больно емкий формат)

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

Соседние файлы в папке лабораторная работа 5 (html, css, js)