MySQL & mSQL

Спецификация CGI


Итак, что в точности представляет собой «набор правил», позволяющий CGI-программе, скажем, в Батавии, штат Иллинойс, обмениваться данными с веб-броузером во Внешней Монголии? Официальную спецификацию CGI наряду с массой других сведений о CGI можно найти на сервере NCSA по адресу http://hoohoo. ncsa.uluc.edu/ cgi/. Однако эта глава для того и существует, чтобы вам не пришлось долго путешествовать и самому ее искать.

Есть четыре способа, которыми CGI передает данные между CGI-npor-раммой и веб-сервером, а следовательно, и клиентом Web:

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

  • Командная строка.

  • Стандартное устройство ввода.

  • Стандартное устройство вывода.

    С помощью этих четырех методов сервер пересылает все данные, переданные клиентом, CGI-программе. Затем CGI-программа делает свое волшебное дело и пересылает выходные данные обратно серверу, который переправляет их клиенту.

    Эти данные приводятся с прикидкой на сервер HTTP Apache. Apache - наиболее распространенный веб-сервер, работающий практически на любой платформе, включая Windows 9х и Windows NT. Однако они могут быть применимы ко всем HTTP-серверам, поддерживающим CGI. Некоторые патентованные серверы, например, от Microsoft и Netscape, могут иметь дополнительные функции или работать несколько иначе. Поскольку лицо Web продолжает изменяться с невероятной скоростью, стандарты все еще развиваются, и в будущем, несомненно, произойдут изменения. Однако, что касается CGI, то эта технология представляется устоявшейся - расплачиваться за это приходится тем, что другие технологии, такие как апплеты, ее потеснили. Все CGI-программы, которые вы напишете, используя эти сведения, почти наверное смогут работать еще долгие годы на большинстве веб-серверов.

    Когда CGI-программа вызывается посредством формы — наиболее распространенного интерфейса, броузер передает серверу длинную строку, в начале которой стоит путь к CGI-программе и ее имя. Затем следуют различные другие данные, которые называются информацией пути и передаются CGI-программе через переменную окружения PATH_INFO (рис. 9-1). После информации пути следует символ «?», а за ним - данные формы, которые посылаются серверу с помощью метода HTTP GET. Эти данные становятся доступными CGI-программе через переменную окружения QUERY_STRING . Любые данные, которые страница посылает с использованием метода HTTP POST, который используется чаще всего, будут переданы CGI-программе через стандартное устройство ввода. Типичная строка, которую может получить сервер от броузера, показана на рис. 9-1. Программа с именем formread в каталоге cgi-bin вызывается сервером с дополнительной информацией пути extra/information и данными запроса choice=help - по-видимому, как часть исходного URL. Наконец, данные самой формы (текст «CGI programming» в поле «keywords») пересылаются через метод HTTP POST .




    Рис. 9-1. Части строки, переданной броузером серверу

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



    Когда сервер выполняет CGI-программу, то прежде всего передает ей некоторые данные для работы в виде переменных окружения. В спецификации официально определены семнадцать переменных, но неофициально используется значительно больше - с помощью описываемого ниже механизма, называемого HTTP_/nec/zams/n. CGI-программа

    имеет доступ к этим переменным так же, как и к любым переменным среды командного процессора при запуске из командной строки. В сценарии командного процессора, например, к переменной окружения F00 можно обращаться как $F00; в Perl это обращение выглядит, как $ENV{'F00'} ; в С - getenv("F00") ; и т. д. В таблице 9-1 перечислены переменные, которые всегда устанавливаются сервером - хотя бы и в значение null. Помимо этих переменных данные, возвращаемые клиентом в заголовке запроса, присваиваются переменным вида HTTP_F00 , где F00 - имя заголовка. Например, большинство веб-броузеров включает данные о версии в заголовок с именем USEfl_AGENT . Ваша CGI-npor-рамма может получить эти данные из переменной HTTP_USER_AGENT .

    Таблица 9-1. Переменные окружения CGI





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



    Описание



    CONTENT_LENGTH



    Длина данных, переданных методами POST или PUT, в байтах.



    CONTENT_TYPE



    Тип MIME данных, присоединенных с помощью методов POST или PUT .



    GATEWAY_INTERFACE



    Номер версии спецификации CGI, поддерживаемой сервером.



    PATH_INFO



    Дополнительная информация пути, переданная клиентом. Например, для запроса http://www.myserver.eom/test.cgi/this/is/a/ path?field=green значением переменной РАТН_ INFO будет /this/is/a/path.



    PATH_TRANSLATED



    То же, что PATH_INFO , но сервер производит всю







    возможную трансляцию, например, расширение имен типа «-account». »



    QUERY_STRING



    Все данные, следующие за символом «?» в URL. Это также данные, передаваемые, когда REQ-UEST_METHOD формы есть GET.



    REMOTE_ADDR



    IP-адрес клиента, делающего запрос.



    REMOTE_HOST



    Имя узла машины клиента, если оно доступно.



    REMOTE_IDENT



    Если веб-сервер и клиент поддерживают идентификацию типа identd, то это имя пользователя учетной записи, которая делает запрос.



    REQUEST_METHOD



    Метод, используемый клиентом для запроса. Для CGI-программ, которые мы собираемся создавать, это обычно будет POST или GET.

    SERVER_NAME Имя узла - или IP-адрес, если имя недоступно, -машины, на которой выполняется веб-сервер.
    SERVER_PORT Номер порта, используемого веб-сервером.
    SERVER_PROTOCOL

    Протокол, используемый клиентом для связи с сервером. В нашем случае этот протокол почти всегда HTTP.
    SERVER_SOFTWARE Данные о версии веб-сервера, выполняющего CGI-программу.


    SCRIPT_NAME



    Путь к выполняемому сценарию, указанный клиентом. Может использоваться при ссылке URL на самого себя, и для того, чтобы сценарии, ссылки на которые существуют в разных местах, могли выполняться по-разному в зависимости от места.

    <


    Приведем пример сценария CGI на Perl, который выводит все переменные окружения, установленные сервером, а также все унаследованные переменные, такие как PATH, установленные командным процессором, запустившим сервер.

    #!/usr/bin/perl -w

    print << HTML;

    Content-type: text/html\n\n

    <HTML><HEAD><TITLE></title></head>

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

    <P> HTML

    foreach (keys %ENV) { print "$_: $ENV{$_}<br>\n"; }

    print <<HTML; </body></html>

    HTML

    Все эти переменные могут быть использованы и даже изменены вашей CGI-программой. Однако эти изменения не затрагивают веб-сервер, запустивший программу.

    Командная строка

    CGI допускает передачу CGI-программе аргументов в качестве параметров командной строки, которая редко используется. Редко используется она потому, что практические применения ее немногочисленны, и мы не будем останавливаться на ней подробно. Суть в том, что если переменная окружения QUERY_STRING не содержит символа « = », то CGI-программа будет выполняться с параметрами командной строки, взятыми из QUERY_STRING . Например, http://www.myserver.com/cgi-bin/finger?root запустит finger root на www.myserver.com.

    Есть две основные библиотеки, обеспечивающие CGI-интерфейс для Perl. Первая из них - cgi-lib.pl Утилита cgi-lib.pl очень распространена, поскольку в течение долгого времени была единственной имеющейся большой библиотекой. Она предназначена для работы в Perl 4, но работает и с Perl 5. Вторая библиотека, CGI.pm, более новая и во многом превосходит cgi-lib.pl. CGI.pm написана для Perl 5 и использует полностью объектно-ориентированную схему для работы с данными CGI. Модуль CGI.pm анализирует стандартное устройство ввода и переменную QUERY_STRING и сохраняет данные в объекте CGI. Ваша программа должна лишь создать новый объект CGI и использовать простые методы, такие как paramQ, для извлечения нужных вам данных. Пример 9-2 служит короткой демонстрацией того, как CGI.pm интерпретирует данные. Все примеры на Perl в этой главе будут использовать CGI.pm.



    Пример 9-2. Синтаксический анализ CGI-данных на Perl

    #!/usr/bin/perl -w

    use CGI qw(:standard);

    # Используется модуль CGI.pm. qw(:standard) импортирует

    # пространство имен стандартных CGI-функций,чтобы получить

    # более понятный код. Это можно делать, если в сценарии

    # используется только один объект CGI.

    $mycgi = new CGI; #Создать объект CGI, который будет 'шлюзом' к данным формы

    @fields = $mycgi->param; # Извлечь имена всех заполненных полей формы

    print header, start_html('CGI.pm test'); ft Методы 'header' и 'start_html',

    # предоставляемые

    # CGI.pm, упрощают получение HTML.

    # 'header' выводит требуемый заголовок HTTP, a

    #'start_html' выводит заголовок HTML с данным названием,

    #a также тег <BODY>.

    print "<р>Данные формы:<br>";

    foreach (@fields) { print $_, ":",- $mycgi->param($_), "<br>"; }

    # Для каждого поля вывести имя и значение, получаемое с помощью

    # $mycgi->param('fieldname').

    print end_html; # Сокращение для вывода завершающих тегов "</body></html>".

    Обработка входных данных в С

    Поскольку основные API для MySQL и mSQL написаны на С, мы не будем полностью отказываться от С в пользу Perl, но там, где это уместно, приведем несколько примеров на С. Есть три широко используемые С-библиотеки для CGI-программирования: cgic Тома Бу-телла (Tom Boutell)*; cgihtml Юджина Кима (Eugene Kim)t и libcgi от EIT*. Мы полагаем, что cgic является наиболее полной и простой в использовании. В ней, однако, недостает возможности перечисления всех переменных формы, когда они не известны вам заранее. На самом деле, ее можно добавить путем простого патча, но это выходит за рамки данной главы. Поэтому в примере 9-3 мы используем библиотеку cgihtml, чтобы повторить на С приведенный выше сценарий Perl.

    Пример 9-3. Синтаксический анализ CGI-данных на С

    /* cgihtmltest.c - Типовая CGI-программа для вывода ключей и их значений

    из данных, полученных от формы */

    #include <stdio.h>



    #include "cgi-lib.h" /* Здесь содержатся все определения функций СGI */

    #include "html-lib.h" /* Здесь содержатся' все определения вспомогательных функций для HTML */

    void print_all(llist 1)

    /* Эти функции выводят данные, переданные формой, в том же формате, что и приведенный выше сценарий Perl. Cgihtml предоставляет также встроенную функцию

    print_entries(), которая делает то же самое, используя формат списка HTML. */ {

    node* window;

    /* Тип 'node' определен в библиотеке cgihtml и ссылается на связанный список, в котором хранятся все данные формы. */

    window = I.head; /* Устанавливает указатель на начало данных формы */

    while (window != NULL) { /* Пройти по связанному списку до последнего (первого пустого) элемента */

    printf(" %s:%s<br>\n",window->entry. name,replace_ltgt(window->entry.value));

    /* Вывести данные. Replace__ltgt() - функция, понимающая HTML-кодировку текста и обеспечивающая его правильный вывод на броузер клиента. */

    window = window->next; /* Перейти к следующему элементу списка. */

    } }

    int main() {

    llist entries; /* Указатель на проанализированные данные*/

    int status; /* Целое число, представляющее статус */

    html__header(); /* Вспомогательная функция HTML, выводящая заголовок HTML*/

    html_begin("cgihtml test");

    /* Вспомогательная функция HTML, выводящая начало страницы HTML с указанным заголовком. */

    status = read_cgi_input(&entries); /* Производит ввод и синтаксический анализ данных формы*/

    printf("<р>Данные формы:<br>");

    print_all(entries); /* Вызывает определенную выше функцию print_all(). */

    html_end(); /* Вспомогательная функция HTML, выводящая конец страницы HTML. */

    list_clear(&entries); /* Освобождает память, занятую данными формы. */

    return 0; }

    Стандартное устройство вывода

    Данные, посылаемые CGI-программой на стандартное устройство вывода, читаются веб-сервером и отправляются клиенту. Если имя сценария начинается с nph-, то данные посылаются прямо клиенту без вмешательства со стороны веб-сервера. В этом случае CGI-программа должна сформировать правильный заголовок HTTP, который будет понятен клиенту. В противном случае предоставьте веб-серверу сформировать HTTP-заголовок за вас.



    Даже если вы не используете nph-сценарий, серверу нужно дать одну директиву, которая сообщит ему сведения о вашей выдаче. Обычно это HTTP-заголовок Content-Type , но может быть и заголовок Location . За заголовком должна следовать пустая строка, то есть перевод строки или комбинация CR/LF.

    Заголовок Content-Type сообщает серверу, какого типа данные выдает ваша CGI-программа. Если это страница HTML, то строка должна быть Content-Type: text/html. Заголовок Location сообщает серверу другой URL - или другой путь на том же сервере, - куда нужно направить клиента. Заголовок должен иметь следующий вид: Location: http:// www. myserver. com/another/place/.

    После заголовков HTTP и пустой строки можно посылать собственно данные, выдаваемые вашей программой, - страницу HTML, изображение, текст или что-либо еще. Среди CGI-программ, поставляемых с сервером Apache, есть nph-test-cgi и test-cgi, которые хорошо демонстрируют разницу между заголовками в стилях nph и не-nph, соответственно.

    В этом разделе мы будем использовать библиотеки CGI.pm и cgic, в которых есть функции для вывода заголовков как HTTP, так и HTML. Это позволит вам сосредоточиться на выводе собственно содержания. Эти вспомогательные функции использованы в примерах, приведенных ранее в этой главе.




    Содержание раздела