Выполнение CGI
После того, как вы
установили CGI, имеются несколько способов
выполнить его. Если ваш CGI -программа, работающая
только с выводом, типа программы Hello,World!, тогда Вы
может выполнять ее, просто обращаясь к ее URL.
Большинство программ выполняется как серверное
приложение к форме HTML. Прежде, чем научиться, как
получать информацию от этих форм, сначала
прочтите краткое введение о создании таких форм.
Быстрая обучающая программа по формам HTML
Два наиболее важных тега в
форме HTML - это теги <form> и <input>. Можно
создавать большинство форм HTML, используя только
эти два тега. В данной главе, Вы изучите эти теги и
небольшое подмножество возможных типов или
атрибутов <input>. Полное руководство и ссылка на
формы HTML находятся в Главе 3 " HTML и формы" .
Тег
<form>
Тег <form> используется
для определения того, какая часть файла HTML должна
быть использована для информации, введенной
пользователем. Здесь имеется в виду, как
большинство страниц HTML вызывает программу CGI.
Атрибуты тега определяют имя программы и
местоположение - либо локально, либо как полный
URL, тип используемого кодирования, и метод
перемещения данных, используемых программой.
Следующая строка показывает спецификации для
тега <form>:
< ACTION FORM = "url" METHOD = [POST |GET] ENCTYPE = "..."
>
Атрибут ENCTYPE не играет особой роли и обычно не
включается с тегом <form>. Подробная информация
относительно тега ENCTYPE дана в Главе 3. Один из
способов использования ENCTYPE, показан в Главе 14
"Фирменные расширения. "
Атрибут ACTION ссылается на URL программы CGI. После
того, как пользователь заполнит форму и
предоставит информацию, вся информация
кодируется и передается программе CGI. Программа
CGI решает сама вопрос о декодировании и обработке
информации; этот аспект рассматривается в
"Принятие ввода от браузера, " ниже в
настоящей главе.
Наконец, атрибут METHOD описывает, как программа CGI
должна получать ввод. Эти два методы - GET и POST -
отличаются в отношении того, как передавать
информацию программе CGI. Оба обсуждены в
"Принятие ввода от браузера. "
Чтобы браузер смог позволить введение
информации пользователем, все теги форм и
информация должны быть окружены тегом <form>. Не
забудьте заключительный тег </form> для
обозначения конца формы. Нельзя иметь форму
внутри формы, хотя Вы можете установить форму,
которая позволяет представлять части информации
в различные местах; этот аспект широко
рассматривается в Главе 3.
Тег <input>
Вы можете создавать
полоски ввода текста, кнопки "radio", окна
флажков, и другие средства принятия ввода,
используя тег<input>. В данном разделе
рассматриваются только поля текстового ввода.
Для реализации этого поля, используйте тег
<input> со следующими атрибутами:
< INPUT TYPE=text NAME = "... " VALUE = "... " SIZE = MAXLENGTH =
>
NAME - символическое имя переменной, которая
содержит значение, введенное пользователем. Если
Вы включаете текст в атрибут VALUE, этот текст будет
помещен как заданный по умолчанию в поле
текстового ввода. Атрибут SIZE позволяет Вам
определить горизонтальную длину поля ввода,
поскольку он будет появляться в окне браузера. И
наконец, MAXLENGTH определяет максимальное число
символов которые, пользователь может ввести в
поле. Обратите внимание, что атрибуты VALUE, SIZE,
MAXLENGTH являются необязательными.
Представление
формы
Если Вы имеете только одно
текстовое поле в пределах формы, пользователь
может представить форму, просто набирая
информацию на клавиатуре и нажимая Enter. В
противном случае, должен быть какой-то другой
способ представления информации пользователем.
Пользователь представляет информацию, используя
кнопку для представления со следующим тегом:
< Input type=submit >
Этот тег создает внутри вашей формы кнопку Submit.
Когда пользователь закончивает заполнение
формы, он или она может отправить ее содержание
по адресу URL, указанному атрибутом ACTION формы,
кликая кнопку Submit.
Принятие
ввода от браузера
Выше были даны примеры
записи программы CGI, которая посылает информацию
с сервера на браузер. В действительности,
программа CGI, которая лишь выводит данные, не
имеет много приложений (некоторые примеры даны в
Главе 4 ). Более важной способностью CGI является
получение информации от браузера - особенность,
которая придает Веб интерактивный характер.
Программа CGI получает два вида информации от
браузера.
* Во-первых, она получает различные части
информации о браузере (его тип, что он может
просматривать, хост хозяина, и так далее), сервера
(его имя и версия, порт его выполнения, и так
далее), и непосредственно о программе CGI (имя
программы и где она расположена). Сервер дает всю
эту информацию программе CGI через переменные
среды.
* Во-вторых, программа CGI может получать
информацию, введенную пользователем. Эта
информация, после кодирования браузером,
посылается либо через переменную среду (метод GET),
либо через стандартный ввод (stdin- метод POST).
Переменные
среды
Полезно знать, какие
переменные среды являются доступными для
программы CGI, как в процессе обучения, так и для
отладки. В таблице 2.2 приведены некоторые из
доступных переменных среды CGI. Можно также
записать программу CGI, которая выводит
переменные среды и их значения на браузер Веб.
Таблица 2.2.
Некоторые важные переменные среды CGI
Переменная среды |
Цель |
REMOTE_ADDR |
Адрес IP машины клиента. |
REMOTE_HOST |
Хост хозяина машины
клиента. |
HTTP _ACCEPT |
Перечисляет типы MIME
данных, которые браузер умеет интерпретировать. |
HTTP _USER_AGENT |
Информация браузера ( тип
браузера, номер версии, операционная система, и
т.д.). |
REQUEST_METHOD |
GET или POST. |
CONTENT_LENGTH |
Размер ввода, если он
послан через POST. Если не имеется никакого ввода
или если используется метод GET, этот параметр не
определен. |
QUERY_STRING |
Содержит вводимую
информацию, когда она передается с помощью
метода GET. |
PATH_INFO |
Позволяет пользователю
определить путь от командной строки CGI (например,
http://hostname/cgi-bin/programname/path). |
PATH_TRANSLATED |
Транслирует
относительный путь в PATH_INFO в фактический путь в
системе. |
Чтобы записать приложение
CGI, которое отображает переменные среды, нужно
знать, как выполнить две вещи:
* Определить все переменные среды и их
соответствующие значения.
* Вывести результаты для браузера.
Вы уже знаете, как
выполнять последнюю операцию. В Perl переменные
среды сохраняются в ассоциативном массиве %ENV,
который вводится именем переменной среды.
Листинг 2.3 содержит env.cgi, программу Perl, которая
служит для достижения нашей цели.
Листинг 2.3.
Программа Perl, env.cgi, которая выводит все
переменные среды CGI.
#!/usr/local/bin/perl
print "Content-type: text/htmlnn";
print "<html> <head>n";
print "<title>CGI Environment</title>n";
print "</head>n";
print "<body>n";
print "<h1>CGI Environment</h1>n";
foreach $env_var (keys %ENV) {
print "<B>$env_var</B> = $ENV{$env_var}<BR>n";
}
print "</body> </html>n";
Подобная программа может
быть написана в C; полный код находится в Листинге
2.4.
Листинг 2.4. Env.cgi.c в C.
/* env.cgi.c */
#include <stdio.h>
extern char **environ;
int main()
{
char **p = environ;
printf("Content-Type: text/htmlrnrn");
printf("<html> <head>n");
printf("<title>CGI Environment</title>n");
printf("</head>n");
printf("<body>n");
printf("<h1>CGI Environment</h1>n");
while(*p != NULL)
printf("%s<br>n",*p++);
printf("</body> </html>n");
}
GET или POST ?
Какая разница между методами GET и POST? GET передает
закодированную входную строку через переменную
среды QUERY_STRING, а POST передает ее через stdin. POST - более
предпочтительный метод, особенно для форм с
большим количеством данных, потому-что здесь нет
каких-либо ограничений в отношении объема
посылаемой информации, а при методе GET объем
пространства среды ограничен. GET имеет однако
определенное полезное свойство; это подробно
рассматривается в Главе 5 "Ввод".
Чтобы определить, который метод используется,
программа CGI проверяет переменную среду REQUEST_METHOD,
которая будет установлена либо в GET, либо в POST.
Если она установлена в POST, длина закодированной
информации сохранена в переменной среды CONTENT_LENGTH.
Закодированный Ввод
Когда пользователь передает форму, браузер
сначала кодирует информацию перед посылкой ее на
сервер, а затем на приложение CGI. Когда Вы
используете тег <input>, каждому полю
присваивают символическое имя. Значение,
введенное пользователем, представляется как
значение переменной.
Чтобы определить это,
браузер использует кодирующую спецификацию URL,
которая может быть описана следующим образом:
* Отделяет различные поля амперсандом
(&).
* Отделяет имя и значения знаками
равенства (=), с именем слева и значением справа.
* Заменяет пробелы знаками "плюс" (+).
* Заменяет все "ненормальные" символы
знаком процента (%), за которым следует двузначный
шестнадцатеричный код символа.
Ваша конечная
закодированная строка будет похожа на следующую:
name1=value1&name2=value2&name3=value3 ...
Примечание |
Спецификации для
кодирования URL находятся в RFC1738. |
Например, предположим, что
у вас была форма, которая запросила имя и возраст.
Код HTML, который использовался для отображения
этой формы, представлен в листинге 2.5.
Листинг 2.5. Код HTML
для отображения формы имени и возраста.
<html> <head>
<title>Name and Age</title>
</head>
<body>
<form action="/cgi-bin/nameage.cgi" method=POST>
Enter your name: <input type=text name="name"><p>
Enter your age: <input type=text name="age"><p>
<input type=submit>
</form>
</body> </html>
Предположим, что
пользователь вводит Joe Schmoe в поле имени, и 20 - в
поле возраста. Ввод будет закодирован во входной
строке.
name=Joe+Schmoe&age=20
Синтаксический
анализ ввода
Для того чтобы эта
информация была полезной, нужно использовать
информацию на что-то такое, что может быть
использовано вашими программами CGI. Стратегии
синтаксического анализа ввода рассматриваются в
Главе 5. Практически, Вам никогда не придется
думать о том, как анализировать ввод, потому что
несколько специалистов уже написали доступные
для всех библиотеки, которые производят
синтаксический анализ. Две такие библиотеки
представлены в настоящей главе в следующих
разделах: cgi -lib.pl для Perl (написаны Стивом
Бреннером) и cgihtml для C (написаны мной).
Общая цель большинства библиотек, написанных на
различных языках, состоит в том, чтобы
анализировать закодированную строку и помещать
пары имен и значений в структуру данных. Имеется
очевидное преимущество в использовании языка,
который имеет встроенные структуры данных типа
Perl; однако, большинство библиотек для языков
низшего уровня типа C и C++ включает выполнение
структуры данных и подпрограммы.
Не обязательно добиваться полного понимания
библиотек; гораздо важнее научиться
использовать их как инструментальные средства,
чтобы упростить работу программиста CGI.
Cgi -lib.pl
Cgi -lib.pl использует ассоциативные массивы Perl.
Функция &ReadParse анализирует входную строку и
вводит каждую пару "имя / значение" по имени.
Например, соответствующими строками Perl,
необходимыми для декодирования только что
представленной вводной строки "имя /
возраст", были бы
&ReadParse(*input);
Теперь, чтобы увидеть значение, введенное для
"имени", можно обращаться к ассоциативному
массиву $input {"имя"}. Точно так же, чтобы
обратиться к значению "возраста", нужно
посмотреть на переменную $input {"возраст"}.
Cgihtml
C не имеет никаких
встроенных структур данных, так что cgihtml
осуществляет свой собственный список связей для
использования со своими анализирующими
подпрограммами CGI. Это определяет структуру entrytype
следующим образом:
Typedef struct {
Char *name;
Char *value;
} Entrytype;
Чтобы проанализировать вводную строку "name /
age" ("имя / возраст") в C, используя cgihtml,
используется следующее:
Llist input; /* объявить связанный список, называемый
вводом */
read_cgi_input(&input); /* анализировть ввод и место в
связанном списке */
Чтобы обратиться к информации о возрасте, можно
либо проанализировать список вручную, либо
использовать имеющуюся функцию cgi _val ().
#include <Stdlib.h>
#include <String.h>
Char *age = malloc (sizeof (char) * strlen (cgi _val (input, "age")) + 1);
Strcpy (age, cgi _val (input, "age"));
Значение "возраста" теперь сохранено в
строке age.
Примечание |
Вместо использования
простого массива (подобно char age [5];), я занимаюсь
динамическим распределением пространства
памяти для строки age. Хотя это усложняет
программирование, тем не менее это важно с точки
зрения безопасности. Более подробно о этом
говорится в Главе 9. |
В Главе 5 глубже
рассматриваются эти и другие библиотеки. На
данный момент, Вы готовы применить свои знания о
вводе и выводе для того, чтобы записать
полноценную, и в то же время простую, программу CGI.
Простая программа CGI
Вы собираетесь записать
программу CGI, называемую nameage.cgi, которая
обрабатывает форму "имя / возраст".
Обработка данных (что я обычно называю
"промежуточным материалом") минимальна.
Nameage.cgi просто декодирует ввод и отображает имя
пользователя и возраст. Хотя не особенно много
пользы от такого инструмента, он демонстрирует
наиболее критический аспект программирования CGI:
ввод и вывод.
Вы используете ту же самую форму, как описано
выше, вызывая поля "имя и возраст". Пока не
стоит беспокоиться об ошибкоустойчивости и
эффективности; решите имеющуюся задачу
простейшим образом. Решения в Perl и C показаны
соответственно в листингах 2.6 и 2.7.
Листинг 2.6. Nameage.cgi в Perl
#!/usr/local/bin/perl
# nameage.cgi
require 'cgi-lib.pl'
&ReadParse(*input);
print "Content-Type: text/htmlrnrn";
print "<html> <head>n";
print "<title>Name and Age</title>n";
print "</head>n";
print "<body>n";
print "Hello, " . $input{'name'} . ". You aren";
print $input{'age'} . " years old.<p>n";
print "</body> </html>n";
Листинг 2.7. nameage.cgi
в C
/* nameage.cgi.c */
#include <stdio.h>
#include "cgi-lib.h"
int main()
{
llist input;
read_cgi_input(&input);
printf("Content-Type: text/htmlrnrn");
printf("<html> <head>n");
printf("<title>Name and Age</title>n");
printf("</head>n");
printf("<body>n");
printf("Hello, %s. You aren",cgi_val(input,"name"));
printf("%s years old.<p>n",cgi_val(input,"age"));
printf("</body> </html>n");
}
Обратите внимание на то,
что эти две программы почти эквивалентны. Они обе
содержат подпрограммы синтаксического анализа,
которые занимают только одну строку и
обрабатывают весь ввод (благодаря
соответствующим библиотечным подпрограммам).
Вывод, по существу, является измененной версией
вашей основной программы Hello, World!.
Попытайтесь выполнить программу, заполняя форму
и нажимая кнопку Submit.
Общая
стратегия программирования
Вы теперь знаете все основные принципы,
необходимые для программирования CGI. Когда Вы
понимаете, как CGI получает информацию и как он
отсылает ее назад браузеру, фактическое качество
вашего конечного продукта зависит от ваших общих
способностей к программированию. А именно, когда
Вы программируете CGI (или вообще что - нибудь, если
уж на то пошло), помните о следующих качествах:
* Простота
* Эффективность
* Универсальность
Первые два качества достаточно распространены:
старайтесь сделать код как можно более читаемым
и эффективным. Универсальность больше относится
к программам CGI, чем к другим приложениям. Когда
Вы начнете разрабатывать свои собственные
программы CGI, Вы узнаете, что имеется несколько
основных приложений, которые хочет сделать
каждый. Например, одна из наиболее
распространенных и очевидных задач программы CGI
является обработка формы и посылка по
электронной почте результатов определенному
получателю. Вы могли бы иметь несколько
отдельных обработанных форм, каждая с различным
получателем. Вместо записи программы CGI для
каждой отдельной формы, Вы можете съэкономить
время, написав более общую программу CGI, которая
годится для всех форм.
Затронув все основные аспекты CGI, я обеспечил Вас
достаточными сведениями, чтобы начать
программирование CGI. Однако чтобы стать
эффективным разработчиком CGI, нужно иметь более
глубокое понимание того, как CGI связывается с
сервером и браузером. В оставшейся части
настоящей книги подробно рассматриваются те
вопросы, о которых вскользь было упомянуто в
данной главе, а также вопросы стратегии
разработки приложений, преимущества и
ограничения протокола.
Резюме
В настоящей главе вкратце были описаны основы
программирования CGI. Вы создаете вывод, правильно
форматируя ваши данные и печатая в stdout. Получение
ввода CGI является несколько более сложным делом,
потому что он должен быть проанализирован до
своего использования. К счастью, уже существуют
несколько библиотек, которые осуществляют
синтаксический анализ.
К данному моменту Вы должны достаточно легко
справиться с программированием приложений CGI.
Оставшаяся часть настоящей книги посвящена
более подробному изложению спецификации,
подсказкам и стратегии программирования более
продвинутых и сложных приложений.
|