1.2 Интерфейс CGI и протокол HTTP

Термин CGI (Common Gateway Interface, общий шлюзовой интерфейс) обозначает набор соглашений, которые должны соблюдаться Web-серверами при выполнении ими различных Web-приложений. В настоящий момент практически повсеместно используется более быстрый и безопасный вариант интерфейса FastCGI. Соглашения, описанные здесь, остаются справедливыми и для него.

Что такое CGI?
Итак, мы набираем в нашем браузере
http://example.com:80/path/to/image.jpg и ожидаем, что сейчас получим HTML-документ (или документ другого формата, например, рисунок). Иными словами, мы рассчитываем, что на хосте в каталоге /path/to/расположен файл image.jpg, который нам сейчас доставят (передаст его, кстати, Webсервер, подключенный к порту 80 на сервере).
Однако на самом деле ситуация несколько иная. По двум причинам.

  • Путь /path/to/, равно как и файл image.jpg на хосте, может вообще не существовать. Ведь администратор сервера имеет возможность задать псевдоним (alias) для любого объекта на сервере. Кроме того, даже если и не назначено никакого псевдонима, все равно имеется возможность так написать программы для Web-сервера, что они будут “перехватывать” каждое обращение к таким путям и соответствующим образом реагировать на это.
  • Файл image.jpg может быть вовсе не графическим документом, а программой, которая в ответ на наш запрос молниеносно запустится, не менее стремительно выполнится и возвратит пользователю результаты своей работы, хотя бы в том же HTML – формате (или, разумеется, в любом другом, — например, это может быть изображение). Пользователь и не догадается, что на самом деле произошло. Для него все равно, загружает ли он документ или невольно запускает программу. Более того, он никак не сможет узнать, что же на самом деле случилось.

Последний пункт особенно впечатляющ. Если вы прониклись его идеей, значит, поняли в общих чертах, что такое CGI. Традиционно программы, работающие в соответствии с соглашениями CGI, называют сценариями, или скриптами — скорее всего из-за того, что в большинстве случаев их пишут на языках-интерпретаторах, подобных Basic (например, на Python или PHP).

Задумаемся на мгновенье. Мы получили довольно мощный механизм, который позволяет нам, в частности, формировать документы “на лету”. К примеру, пусть нам нужно, чтобы в каком-то документе проставлялись текущая дата и время. Разумеется, мы не можем заранее прописать их в документе — ведь в зависимости от того, когда он будет загружен пользователем, эта дата должна меняться. Зато мы можем написать сценарий, который вычислит дату, вставит ее в документ и затем передаст его пользователю, который даже ничего и не заметит!

Однако в построенной нами модели не хватает одного звена. Действительно, предположим, нам нужно, чтобы время в нашей странице проставлялось на основе часового пояса пользователя. Как сценарий узнает, какой часовой пояс у региона, в котором живет этот человек, или какую-нибудь другую информацию, которую может предоставить пользователь? Видимо, должен быть какой-то механизм, позволяющий пользователю не только получать, но также и передавать информацию серверу (в данном случае, например, поправку времени в часах относительно Москвы). Это тоже обеспечивает CGI.

Однако вернемся прежде к URL.

Секреты URL
Помните, мы в предыдущей главе описывали, как выглядит URL? Так вот, это был только частный случай. На самом деле URL имеет более “длинный” формат:
http://example.com:80/path/to/image.jpg?parameters
Как нетрудно заметить, может существовать еще строка parameters, следующая после вопросительного знака. В некоторой степени она аналогична командной строке ОС. В ней может быть все, что угодно, она может быть любой длины (однако следует учитывать, что некоторые символы должны быть URL-закодированы, см. ниже). Вот как раз эта-то строка и передается CGI-сценарию.

Вернемся к нашему предыдущему примеру. Теперь пользователь может указать свой часовой пояс сценарию, например, так:
http://example.com/script.cgi?time=+3

Сценарий с именем script.cgi, после того как запустится и получит эту строку параметров, должен ее проанализировать (например, создать переменную time и присвоить ей значение +3, т. е. 3 часа вперед) и дальше работать как ему нужно. Обращаем ваше внимание на то, что принято параметры сценариев указывать именно в виде
переменная=значение
А если нужно передать несколько параметров (например, не только часовой пояс, но и имя пользователя)? Сделаем это следующим образом:
http://example.com/script.cgi?time=+5&name=Vasya
При этом принято разделять параметры с помощью символа амперсанда &.

Способ посылки параметров сценарию, когда данные помещаются в командную строку URL, называется методом GET. Фактически, даже если не передается никаких параметров (например, при загрузке статической страницы), все равно применяется метод GET. Всё? Нет, не всё. )) Существует еще один распространенный способ (не менее распространенный) — метод POST, но давайте прежде рассмотрим, на каком языке “общаются” браузер и сервер.

GET
Формат:
GET сценарий?параметры HTTP/1.0
Переменные окружения: REQUEST_URI; в переменной QUERY_STRING сохраняется значение параметры, в переменной REQUEST_METHOD — ключевое слово GET.

Строка сценарий?параметры задается в том же самом формате, в котором она входит в URL. Неплохо было бы назвать эту строку как-нибудь более реалистично, чтобы учесть возможность присутствия в ней командных параметров. Такое название действительно существует и звучит как URI (Universal Resource Identifier, универсальный идентификатор ресурса). Очень часто его смешивают с понятием URL (вплоть до того, что это происходит даже в официальной документации по стандартам HTTP). Давайте договоримся, что в будущем мы всегда будем называть словом URL полный путь к некоторой Web-странице вместе с параметрами, и условимся, что под словом URI будет пониматься его часть, расположенная после имени (или IP-адреса) хоста и номера порта.

POST
Формат:
POST сценарий?параметры HTTP/1.0
Переменные окружения: REQUEST_URI; в переменной QUERY_STRING сохраняется значение параметры, в переменной REQUEST_METHOD — слово POST. Этот заголовок используется при передаче данных методом POST.

Мы подошли к сути метода POST. А что, если мы в предыдущем примере зададим вместо GET слово POST и после последнего заголовка (маркера \n\n) начнем передавать какие-то данные? В этом случае сервер их воспримет и также передаст сценарию. Только нужно не забыть проставить заголовок Content-length в соответствии с размером данных, например:

POST /script.cgi HTTP/1.1\n
Host: example.com
Content-length: 5\n
\n
Test!

Сервер начнет обработку запроса, не дожидаясь передачи данных после маркера конца заголовков. Иными словами, сценарий запустится сразу же после отправки \n\n, а уж ждать или не ждать, пока придет строка Test! длиной 5 байтов — его дело.

Зачем нужен метод POST? В основном для того, чтобы передавать большие объемы данных. Например, при загрузке файлов через Web или при обработке больших форм. Кроме того, метод POST часто используют для эстетических целей: дело в том, что при применении GET, как вы, наверное, уже заметили, URL сценария становится довольно длинным и неизящным, а POST-запрос оставляет URL без изменения.

Использование формы
Что теперь нам следует сделать, чтобы пользователь мог в удобной форме ввести свое имя и возраст? Очевидно, придется создать что-то вроде диалогового окна Windows, только в браузере. Итак, нам понадобится обычный HTML-документ (например, с именем getform.htm и расположенный в корневом каталоге) с элементами этого диалога —полями ввода и кнопкой, при нажатии которой запустится наш сценарий. Текст этого документа приведен в листинге:

<!DOCTYPE html>
<html lang=”ru”>
<head>
<title>Документ с формой</title>
<meta charset=’utf-8′>
</head>
<body>
<form action=”script.cgi” method=”GET”>
Введите имя:
<input type=”text” name=”name” value=”Неизвестный”><br>
Введите дату рождения:
<input type=”text” name=”born” value=”Неизвестно”><br>
<input type=”submit” value=”Нажмите кнопку”>
</form>
</body>
</html>

Загрузим наш документ в браузер. Получим форму:


  Документ с формой
  
Введите имя:

Введите дату рождения:

 

Теперь, если занести в поле name свое имя, а в поле для возраста — возраст и нажать кнопку Нажмите кнопку, браузер обратится к сценарию по URL, указанному в атрибуте action тега <form> формы:
http://example.com/script.cgi

Он передаст через ? все параметры, которые помещены внутрь тегов <input> в форме, отделяя их амперсандом (&). Имена полей и их значения будут разделены знаком =.
Теперь вы понимаете, почему мы с самого начала использовали эти символы? Итак, реальный URL, который сформирует браузер при старте сценария, будет таким (учитывая, что на странице был пользователь по имени Thomas, и он родился 11 марта 1962 г.):
http://example.com/script.cgi?name=Thomas&born=1962-03-11

В данной теме мы получили базовое представление о протоколе HTTP и интерфейсе CGI, используемых в Web. Мы также узнали, какую роль играют заголовки протокола HTTP при обмене данными между браузером и сервером.

Залишити відповідь