Опубликован: 15.08.2003 | Уровень: для всех | Доступ: платный | ВУЗ: Российский государственный гуманитарный университет
Лекция 1:

Общие сведения

Лекция 1: 123 || Лекция 2 >

Спецификация Common Gateway Interface

Данная спецификация определяет стандартный способ обмена данными между прикладной программой и HTTP-сервером. Спецификация была предложена для сервера NCSA и является основным средством расширения возможностей обработки запросов клиентов HTTP-сервером.

В CGI имеет смысл выделить следующие основные моменты:

  • понятие CGI-скрипта ;
  • типы запросов;
  • механизмы приема данных скриптом;
  • механизм генерации отклика скриптом.

Основное назначение CGI — обработка данных из HTML-форм. В настоящее время область применения CGI гораздо шире.

Понятие CGI-скрипта

CGI-скриптом называют программу, написанную на любом языке программирования или командном языке, которая осуществляет обмен данными с HTTP-сервером в соответствии со спецификацией Common Gateway Interface .

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

Типы запросов

Различают два типа запросов к CGI-скриптам: по методу GET и по методу POST. В свою очередь, запросы по методу GET подразделяются на запросы по типам кодирования: isindex и form-urlencoded, а запросы по методу POSTmultipart/form-data и form-urlencoded.

В запросах по методу GET данные от клиента передаются скрипту в переменной окружения QUERY_STRING. В запросах по методу POST данные из формы передаются в потоке стандартного ввода скрипта. При передаче через поток стандартного ввода в переменной окружения CONTENT_LENGTH указывается число передаваемых символов.

Запрос типа ISINDEX — это запрос вида:

http://intuit.ru/somthing-cgi/cgi-script?word1+word2+word3

Главным здесь является список слов после символа "?". Слова перечисляются через символ "+" и для кириллицы в шестнадцатеричные последовательности не кодируются. Последовательность слов после символа "?" будет размещена в переменной окружения QUERY_STRING.

Запрос типа form-urlencoded — это запрос вида:

http://intuit.ru/somthing-cgi/cgi-script?field=word1&field2=word2

Данные формы записываются в виде пар "имя_поля=значение", которые разделены символом "&".

Приведенный пример — это обращение к скрипту по методу GET. Все символы после "?" попадут в переменную окружения QUERY_STRING. При этом если в значениях полей появляется кириллица или специальные символы, то они заменяются шестнадцатиричным кодом символа, который следует за символом "%".

При обращении к скрипту по методу POST данные после символа "?" не будут размещаться в QUERY_STRING, а будут направлены в поток стандартного ввода скрипта. В этом случае количество символов в потоке стандартного ввода скрипта будет указано в переменной окружения CONTENT_LENGTH.

При запросе типа multipart/form-data применяется составное тело HTTP-сообщения, которое представляет собой данные, введенные в форме, и данные присоединенного внешнего файла. Это тело помещается в поток стандартного ввода скрипта. При этом к данным формы применяется кодирование как в form-urlencoded, а данные внешнего файла передаются как есть.

Механизмы приема данных скриптом

Скрипт может принять данные от сервера тремя способами:

  • через переменные окружения;
  • через аргументы командной строки;
  • через поток стандартного ввода.

При описании этих механизмов будем считать, что речь идет об обмене данными с сервером Apache для платформы Unix.

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

При вызове скрипта сервер выполняет системные вызовы fork и exec. При этом он создает среду выполнения скрипта, определяя ее переменные. В спецификации CGI определены 22 переменные окружения. При обращении к скрипту разными методами и из различных контекстов реальные значения принимают разные совокупности этих переменных. Например, при обращении по методу POST переменная QUERY_STRING не имеет значения, а по методу GET — имеет. Другой пример — переменная окружения HTTP_REFERER. При переходе по гипертекстовой ссылке она определена, а если перейти по значению поля location или через JavaScript-программу, то HTTP_REFERER определена не будет.

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

#Perl
$a = $ENV{CONTENT_LENGTH};
...
// C
a = getenv("CONTENT_LENGTH");

В случае доступа к скрипту по методу GET данные, которые передаются скрипту, размещаются в переменной окружения QUERY_STRING.

Аргументы командной строки

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

#Perl
foreach $a (@ARGV)
{
print $a,"\n";
}

// C
void main(argc,argv)
int argc;
char *argv[];
{
int i;
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
}

В обоих примерах показана распечатка аргументов командной строки для программ на Perl и C соответственно.

Аргументы командной строки появляются только в запросах типа ISINDEX.

Поток стандартного ввода

Ввод данных в скрипт через поток стандартного ввода осуществляется только при использовании метода доступа к ресурсу (скрипту) POST. При этом в переменную окружения CONTENT_LENGTH помещается число символов, которое необходимо считать из потока стандартного ввода скрипта, а в переменную окружения CONTENT_TYPE помещается тип кодирования данных, которые считываются из потока стандартного ввода.

При посимвольном считывании в C можно применить, например, такой фрагмент кода:

int n;
char *buf;
n= atoi(getenv("CONTENT_LENGTH"));
buf = (char *) malloc(n+1);
memset(buf,'\000',n+1);
for(i=0;i<n;i++)
{
buf[i]=getchar();
}

free(buf);

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

Механизм генерации отклика скриптом

Существует только один способ вернуть данные серверу и, соответственно, браузеру пользователя — писать в поток стандартного вывода (STDOUT). При этом скрипт должен формировать HTTP-сообщение.

Сначала выводятся директивы HTTP-заголовка. В минимальном варианте это либо

Content-type: text/html,

либо

Location: http://intuit.ru/

В первом случае определяется тип тела HTTP-сообщения, а во втором осуществляется перенаправление запроса.

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

#!/bin/sh
echo Content-type: text/plain
echo
echo Hello

В данном случае используется командный интерпретатор sh.

Если скрипт начинает формирование заголовка с директивы версии HTTP-протокола, то сервер не анализирует отклик и передает его как есть. Если в заголовке, сгенерированном скриптом, эта директива отсутствует, то сервер считает, что заголовок неполный, и вставляет в него дополнительные директивы.

Лекция 1: 123 || Лекция 2 >
Екатерина Cколова
Екатерина Cколова
Россия, Москва
Dima Semenchenok
Dima Semenchenok
Россия