CGI-скрипт представляет собой программу, запускаемую демоном httpd, выполняющую какие-то действия и возвращающую данные демону httpd для передачи их пользователю в броузер. CGI-скрипт является шлюзом ( как следует из названия Common Gateway Interface ), который во взаимодействии с такими прикладными системами, как СУБД, электронные таблицы, системы обработки графической информации и т.д. возвращает пользователю ответ на его запрос в виде HTML-страницы, GIF-картинки или другого средства представления информации.

CGI-скрипт ( в дальнейшем я буду просто писать “скрипт”, лень постоянно на английский переключаться….:)), на каком бы языке он не был написан, получает от демона httpd информацию тремя способами:

  1. Через переменные окружения.
  2. Через командную строку.
  3. Через стандартный ввод.

Возвращает скрипт эту информацию через стандартный вывод.

Переменные окружения

Вот список переменных окружения и их значения:

CHARSET = windows-1251
CHARSET_DETERMINED_BY = UserAgent
CHARSET_HTTP_METHOD = http://
CHARSET_SERVER_NAME = in-hosting.agava.ru:80
CHARSET_SERVER_PORT = 80
DATE_GMT = Thursday, 09-Nov-2000 05:42:06 GMT
DATE_LOCAL = Thursday, 09-Nov-2000 08:42:06 MSK
DOCUMENT_NAME = cgi.html
DOCUMENT_PATH_INFO =
DOCUMENT_ROOT = /home
DOCUMENT_URI = /d/dhls.agava.ru/WWW/cgi.html
GATEWAY_INTERFACE = CGI/1.1
HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
HTTP_ACCEPT_CHARSET = iso-8859-1,*,utf-8
HTTP_ACCEPT_ENCODING = gzip
HTTP_ACCEPT_LANGUAGE = en
HTTP_CONNECTION = close
HTTP_COOKIE = DHLinuxSiteMenu=0000010000; b=b
HTTP_HOST = dhls.agava.ru
HTTP_REFERER = http://dhls.agava.ru/cgi-bin/treemenu.pl?toggle=180&rand=501489
HTTP_USER_AGENT = Mozilla/4.7 [en] (Win98; I)
HTTP_X_FORWARDED_FOR = 195.248.164.150
LAST_MODIFIED = Tuesday, 18-Jul-2000 22:31:42 MSD
PATH = /usr/local/bin:/usr/bin:/bin
PERLLIB = /site/perl/sys:/site/perl/lib
QUERY_STRING =
REMOTE_ADDR = 194.67.45.131
REMOTE_PORT = 3656
REQUEST_METHOD = GET
REQUEST_URI = /d/dhls.agava.ru/WWW/cgi.html
SCRIPT_FILENAME = /home/d/dhls.agava.ru/cgi/env.pl
SCRIPT_NAME = /cgi-bin/env.pl
SCRIPT_URI = http://in-hosting.agava.ru/d/dhls.agava.ru/WWW/cgi.html
SCRIPT_URL = /d/dhls.agava.ru/WWW/cgi.html
SERVER_ADDR = 172.16.1.6
SERVER_ADMIN = webmaster@agava.com
SERVER_NAME = in-hosting.agava.ru
SERVER_PORT = 80
SERVER_PROTOCOL = INCLUDED
SERVER_SOFTWARE = Apache/1.3.9 (Unix) PHP/3.0.12 AGAVA.Banners/1.10 rus/PL29.0
SOURCE_CHARSET = windows-1251
USER_NAME = dhls1

Переменные окружения , которые не зависят от типа запроса:

SERVER_SOFTWARE - показывает название и версию http-сервера в формате: название/версия.
SERVER_NAME - показывает доменное имя сервера.
SERVER_ADDR - показывает IP сервера.
SERVER_ADMIN - e-mail администратора web-сервера.
GATEWAY_INTERFACE - версия CGI на момент компиляции httpd демона в формате: CGI/версия
DATE_GMT - текущие дата и время во временной зоне GMT.
DATE_LOCAL - текущие дата и время во временной зоне сервера.
DOCUMENT_ROOT - путь к главному каталогу web-сервера.

Переменные окружения, которые зависят от типа запроса:

SERVER_PROTOCOL - протокол, по которому был получен запрос.
SERVER_PORT - порт, на который был получен запрос.
REQUEST_METHOD - тип запроса: POST,GET и т.д..
REQUEST_URI - страница, отправившая запрос.
SCRIPT_NAME - URL скрипта без имени сервера.
SCRIPT_FILENAME - полное имя файла скрипта на диске.
QUERY_STRING - информация, содержащаяся в командной строке вызова скрипта ( после ? в URL’е )
CONTENT_TYPE - MIME-тип данных, передаваемых скрипту.
CONTENT_LENGTH - длина передаваемых данных.

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

REMOTE_ADDR - IP пользователя.( На hosting.agava.ru, на котором находится моя страница, REMOTE_ADDR всегда равен IP hosting.agava.ru. Это не правильно, но это не мои проблемы…:) )
REMOTE_PORT - порт, открытый на машине пользователя броузером.

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

Имя такой переменной формируется из “HTTP_”+имя заголовка. Причем все символы “-” (тире) в имени заголовка заменяются на символы “_” (подчеркивание). Примеры:

HTTP_ACCEPT - список MIME-типов, которые клиент может обработать.
HTTP_USER_AGENT - в частном случае - броузер, который использует пользователь.
HTTP_REFERER - URL страницы, с которой пришел на текущую страницу пользователь.

Запросы по методу GET

При запросе по методу GET тело запроса передается в командную строку скрипта. Т.е. если запрашиваемый URL http://www.somesite.com/cgi-bin/somescript.cgi, то вызываться от будет так http://www.somesite.com/cgi-bin/somescript.cgi?тело_запроса. Все тело запроса передается в переменную окружения QUERY_STRING, тип данных запроса в CONTENT_TYPE, длина в CONTENT_LENGTH.

Запросы по методу POST

При запросе по методу POST тело запроса передается в стандартный поток ввода скрипта, тип данных запроса в CONTENT_TYPE, длина в CONTENT_LENGTH.

Независимо от метода запроса данные передаются в виде шестнадцатиричных символов типа “%2F”(”/”), кроме печатаемых символов. Поэтому предварительно надо позаботиться о перекодировке в нормальные символы последовательности типа “Thanx%20for%20your%20help%21″. А также заменить “+” на ” “.

Ответ на запрос

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

  1. Content-type - представляет собой MIME-тип возвращаемых данных.
  2. Location - это поле используется в случае, если возвращаются не сами данные а ссылка на них. Представляет собой URL.
  3. Status - используется для задания серверу http строки-статуса. Представляет собой 3-х цифровой код статуса, затем через пробел строку причины. Например - 404 Not Found.

Затем, через пустую строку, состоящую только из символа переноса строки, следует тело ответа.

Вызов скрипта

Скрипт можно вызвать разными способами. Самые распространенные из них:

  1. По URL’у - с помощью тэга A HREF, с помощью атрибута ACTION тэга FORM , напрямую задать url в броузере.
    В этом случае если скрипт возвращает HTML-документ, он должен вывести http-заголовок ( “Content-type=text/html” ), затем сам HTML-документ начинающийся с тэга HTML и содержащий тэг BODY.
  2. С помощью exec cgi - в тело вызывающего скрипт HTML документа помещается комментарий такого вида:
    <!–#exec cgi=”http://www.somesite.com/cgi-bin/somescript.cgi”–>
    или
    <!–#include virtual=”http://www.somesite.com/cgi-bin/somescript.cgi”–>
    Полный URL не обязательно указывать. Можно и относительный - “cgi-bin/somescript.cgi”, если cgi-bin расположена в том же каталоге, что и html-страница, из которой вызывается скрипт.
    В этом случае скрипт обязательно должен возвращать HTML-документ, вывод начинается с http-заголовка, затем следует HTML-документ, не содержащий тэгов HTML и BODY.
  3. С помощью тэга IMG SRC - в данном случае скрипт должен возвращать какую-нибудь картинку. Т.е. сначала http-заголовок, содержащий “Content-type: image/gif”, “Content-type: image/jpg” и т.д., а затем содержание картинки в выбранном формате. Такой способ используется в графических счетчиках посетителей, системах обмена баннерами и т.д.

Обработка форм

Тэг FORM имеет следующий синтаксис:

<FORM ACTION=”url” METHOD=”POST | GET” ENCTYPE=”application/x-www-form-urlencoded”>
<INPUT | SELECT | TEXTAREA…..>
………………..
</FORM>

где url может быть URL’ом скрипта, командой “mailto:” и т.д. METHOD - тип запроса, ENCTYPE применяется только для METHOD=”POST” и имеет только одно значение - application/x-www-form-urlencoded.

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

<INPUT TYPE=”type” NAME=”name” VALUE=”value”…..>

Тэг INPUT имеет следующие атрибуты:

  1. TYPE - тип элемента:
    hidden - пользователь не видит этого элемента, но его значение передается скрипту.
    image - картинка, на которую можно кликнуть.:)
    text - однострочное поле ввода текста.
    password - поле ввода пароля, вводимые символы изображаются в виде звездочек.
    checkbox - кнопка-переключатель, при нажатии на которую меняется ее значение на “on” или “off”.
    radio - кнопка-переключатель, которая как и предыдущая может иметь значения “on” или “off”, отличие от предыдущей в том, что если одна из таких кнопок на форме имеет значение “on”, все остальные кнопки такого же типа и с тем же параметром NAME, должны иметь значение “off”.( Не слишком навороченное определение? ;) Как понимаю - так и описываю…:))
    submit - кнопка, при нажатии на которую данные формы передаются скрипту.
    reset - кнопка устанавливающая во всех полях формы значения по умолчанию.
  2. NAME - имя поля.
  3. VALUE - начальное значение поля. Для кнопок типа radio и checkbox - “on” или “off”. Для кнопок типа “submit” и “reset” - это надпись на кнопке.

Остальные атрибуты INPUT я рассматривать не буду. Они не столь важны для работы скрипта.

Тэг SELECT создает на форме выпадающее меню. Тэг имеет следующий синтаксис:

<SELECT NAME=”name”>
<OPTION> Option1
<OPTION> Option2
…………
</SELECT>

Тэг SELECT имеет следующие атрибуты:

  1. NAME - имя поля.
  2. MULTIPLE - задает возможность множественного выбора.

Тэг OPTION имеет следующие атрибуты:

  1. SELECTED - задает выбранную опцию по умолчанию.

Тэг TEXTAREA создает на форме поле ввода многострочного текста. Тэг имеет следующий синтаксис:

<TEXTAREA NAME=”name” ROWS=количество_строк COLS=количество_столбцов>
Тест, который будет содержать поле по умолчанию
</TEXTAREA>

Тэг TEXTAREA имеет следующие атрибуты:

  1. NAME - имя поля.
  2. ROWS - высота.
  3. COLS - ширина.

Отправка содержания формы происходит при нажатии кнопки “submit”. При отправке формы по методу GET, скрипт, указанный в атрибуте ACTION тэга FORM содержимое формы передается в командную строку скрипта после символа “?” в виде:

name1=value1&name2=value2&…….&nameN=valueN

где nameX - имя поля формы, а valueX - его значение. Для полей ввода текста или пароля значением будет их содержание, введенное пользователем или установленное по умолчанию, а для chekbox и radio значение, определенное в атрибуте VALUE, будет передано только для отмеченных кнопок. При METHOD=”POST” строка формируется также, но передается в стандартный поток ввода.

(c)Ерижоков А.А., 2000.
Использование данного документа разрешено только с согласия автора и с указанием первоисточника: DH’s Linux Site