Разработка cgi


Содержание

Разработка cgi

Эта статья продолжает серию, посвященную программированию Интернет-приложений в Borland Kylix. На этот раз речь пойдет о CGI-приложениях и модулях сервера Apache.

CGI-приложения

Изначально протокол HTTP создавался для передачи по Сети документов в формате HTML и сопутствующей им графики, однако Web-броузеры оказались настолько удобны, что всемирная паутина очень быстро начала обрастать различными дополнительными функциями. Весьма заманчиво выглядит возможность использовать броузер клиента в качестве интерфейса для взаимодействия с удаленным приложением. Такое взаимодействие, разумеется, требует наличия механизма передачи команд и данных от клиента серверу. Для стандартизации механизма передачи команд клиента серверу был разработан стандарт CGI. В общих чертах работа CGI выглядит следующим образом: клиент загружает HTML страницу, содержащую форму и посылает серверу определенный в форме запрос (request), в котором указано действие (action) и список параметров. Действие представляет собой указатель на CGI-приложение, которое должно выполнить запрос. Например действие /cgi-bin/frenchwines указывает на приложение frenchwines. Для одного приложения можно определить несколько действий, которые идентифицируются как отдельные сетевые ресурсы: /cgi-bin/frenchwines, /cgi-bin/frenchwines/, /cgi-bin/frenchwines/welcome – это разные действия приложения frenchwines. Список параметров представляет собой перечень имен параметров и их значений. Если HTML форма использует для передачи параметров метод GET, список параметров можно увидеть в адресной строке броузера после идентификатора ресурса (он отделен от идентификатора символом ‘?’). С точки зрения протокола HTTP CGI-запрос является командой на загрузку некоторого ресурса. В ответ на запрос сервер обычно посылает клиенту HTML документ, который как правило является динамической страницей, т. е. не хранится на диске в виде файла, а генерируется приложением.

CGI–функции могут быть реализованы на сервере в двух вариантах: в форме CGI-сценариев (CGI scripts) и в виде CGI приложений. CGI приложения представляют собой исполнимые модули, вызываемые Web-сервером. Схема взаимодействия между броузером, сервером и CGI-модулем приводится на рисунке. По своей структуре CGI приложение является обычной консольной программой. Сервер передает данные CGI приложению через переменные окружения и стандартный поток ввода, а CGI приложение передает данные серверу через свой стандартный поток вывода. Сервер запускает новую копию приложения для обработки каждого запроса. По окончании обработки запроса CGI-приложение завершается .

Далее следует пример простейшего CGI приложения, написанного в Borland Kylix. Этот пример не использует специальные средства разработки CGI приложений, входящие в состав Kylix. Модуль Libc используется для того, чтобы сделать приложение более компактным. В принципе нам было бы достаточно одного модуля SysUtils.

Для того, чтобы проверить работу примера, скомпилируйте проект simplecgi.dpr (исходный текст лежит здесь) и скопируйте полученный исполнимый файл в каталог CGI-приложений Web-сервера. В Linux Mandrake этим каталогом по умолчанию является /var/www/cgi-bin/ (естественно, сам Web-сервер должен быть установлен и запущен в вашей системе). Затем откройте в броузере страницу TestCGI.html. Страница TestCGI содержит две формы для передачи параметров приложению. Одна форма использует для передачи данных метод GET, другая – метод POST.

Кроме возможности создания CGI-приложений “с нуля”, Borland Kylix располагает весьма удобными специальными средствами разработки приложений для Web-сервера. Kylix может создать для вас “заготовку” CGI-приложения. В окне New выберите элемент Web Server Application и в открывшемся диалоговом окне – пункт CGI standalone executable.

В качестве примера такого приложения мы рассмотрим программу, реализующую Web-интерфейс к базе данных Borland Interbase. Для компиляции и выполнения этого примера вам понадобится сервер баз данных Interbase (входит в комплект поставки Kylix SDE). Перед началом работы с примером Web-интерфейса базы данных, убедитесь, что серверы Web и Interbase установлены и нормально работают.

Приложение-пример (исходный текст лежит здесь) называется fenchwines и представляет собой Web-интерфейс к базе данных французских вин. (Напомню, что “Kylix” в переводе означает “винная чаша”, так что “винная” тематика вполне соответствует рассматриваемому продукту. Для правильной компиляции и запуска демонстрационного приложения необходимо выполнить следующее: скачайте архив с базой данных, распакуйте его, скопируйте файл vina.gdb в какой-нибудь каталог. В корневом каталоге http документов вашего сервера (часто это / var/www/html) создайте каталог wdb и скопируйте в него файлы wctempl.html и barrels.jpg из архива приложения. Теперь откройте приложение в среде Kylix. При помощи менеджера проекта откройте окно Web-модуля, которое связано с модулем main. В окне Web-модуля щелкните правой кнопкой мыши по компоненту SQLConnection1 и в открывшемся меню выберите пункт Edit Connection Properties. В открывшемся диалоговом окне создайте новое соединение. В качестве драйвера базы данных выберите INTERBASE. В поле Database задайте абсолютный путь к файлу vina.gdb. Убедитесь, что поля Password и User_Name содержат значения masterkey и SYSDBA соответственно. Свойство Connection компонента SQLConnection1 должно указывать на новое соединение. Далее отредактируйте свойство HTMLFile компонента PageProducer1 так, чтобы оно содержало полный путь к файлу wctempl.html. Скомпилируйте приложение frenchwines и скопируйте исполнимый файл в каталог CGI-приложений (cgi-bin). Для того, чтобы проверить работу нашего приложения в окне броузера наберите http://localhost/cgi-bin/frenchwines. При этом в окне броузера появится приветственная HTML-страница. Форма на странице позволяет выбирать вина из базы данных по происхождению и категории. Для того, чтобы отобразить все вина, содержащиеся в базе, необходимо ввести “any” в обоих полях формы.

Структура CGI-приложения очень похожа на структуру обычного приложения Kylix. Вместо объекта TApplication в Web-приложении используется объект TWebApplication, а роль класса TForm выполняет класс TWebModule. Потомок класса TWebModule является владельцем всех компонентов, используемых в Web-приложении и ему же принадлежат методы обработки событий.

Окно компонента TWebModule с дочерними компонентами

Важнейшим элементом TWebModule является список действий Actions. В этом списке хранятся объекты TWebActionItem, определяющие действия приложения. Свойство PathInfo объекта TWebActionItem позволяет задать идентификатор действия. Если свойство PathInfo содержит пустую строку, идентификатором данного действия является само имя CGI-приложения. В других случаях идентификатор действия должен предваряться символом “/”. В следующей таблице показаны примеры значений PathInfo и соответствующие им действия для приложения frenchwines, расположенного в директории /cgi-bin/.

Значение PathInfo Действие
“” /cgi-bin/frenchwines
“/” /cgi-bin/frenchwines/
“/welcome” /cgi-bin/frenchwines/welcome
/error /cgi-bin/frenchwines/error

Список Actions можно заполнить в процессе разработки приложения при помощи редактора списка. Для того, чтобы открыть окно редактора нужно в окне инспектора объектов щелкнуть по кнопке с многоточием в поле свойства Actions.

Свойство MethodType объекта TWebActionItem позволяет указать метод передачи параметров для данного действия. Метод, указанный в свойстве MethodType должен соответствовать методу, указанному в тэге FORM HTML страницы, генерирующей запрос. Значение mtAny позволяет действию обрабатывать любые запросы.

Для объекта TWebActionItem определено единственное событие – OnAction. Когда Web-сервер получает CGI-запрос, он запускает соответствующее CGI-приложение и передает ему всю необходимую информацию. В Kylix-приложении диспетчер запросов определяет, какому действию адресован запрос, и вызывает обработчик события OnAction этого действия. После выполнения обработчика OnAction приложение завершается.

Заголовок обработчика выглядит следующим образом:

type THTTPMethodEvent = procedure (Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean) of object;

Объект Request содержит данные о поступившем запросе. Свойства этого объекта позволяют получить сведения об адресе удаленной машины, программном обеспечении клиента, методе запроса и т. п. Для CGI-запроса в объекте Request передается также список параметров запроса. Список параметров хранится в свойстве ContentFields (если запрос передан посредством метода POST) или QueryFields (если использовался метод GET). Оба свойства имеют тип TStrings и содержат набор строк вида

Объект Response описывает ответные действия приложения. Текст HTML страницы, возвращаемой приложением, передается в свойстве Content объекта Response. В простейшем CGI-приложении обработчик OnAction может выглядеть следующим образом:

Рассмотрим другие примеры. В приложении frenchwines главная HTML-страница выводится при выполнении действия frenchwines/welcome. Однако, пользователь может набрать в строке броузера просто . /frenchwines или . /frenchwines/ и было бы очень удобно, если бы в этой ситуации приложение автоматически перенаправляло броузер пользователя на страницу frenchwines/welcome. Для того, чтобы приложение fenchwines выполняло такое перенаправление, в нем заданы два действия, значениями PathInfo которых являются соответственно пустая строка и символ “/”. Обоим действиям можно назначить один и тот же обработчик OnAction:

Статус-код 301 сообщает клиенту о необходимости перенаправить запрос по новому адресу. А что произойдет, если клиент пошлет запрос на выполнение действия, которое не определено в CGI-приложении, например frenchwines/querydb ? В этом случает Kylix-приложение сгенерирует исключение и Web-сервер выдаст неприятное сообщение о внутренней ошибке. Для того, чтобы обращение к неопределенному действию не приводило к исключительной ситуации, необходимо создать еще одно действие и присвоить свойству Default соответствующего объекта TWebActionItem значение True. Теперь это действие будет вызываться для всех запросов, вызывающих неопределенные действия. Обработчик события OnAction этого действия может выглядеть следующим образом:

Генераторы контента

Во всех приведенных выше примерах HTML страницы, возвращаемые сервером задавались в явном виде, путем присвоения строки HTML команд свойству Content. Очевидно, что для вывода сложных страниц с большим числом элементов такой подход непригоден. Для облегчения решения этой проблемы Kylix предоставляет несколько специальных компонентов-генераторов контента (content producers). На вкладке Internet панели компонентов Kylix раположены четыре компонента-генератора: TPageProducer, TDataSetTableProducer, TSQLQueryTableProducer и TDataSetPageProducer.

Компонент TPageProducer генерирует страницу на основе заданного шаблона. Идея этого компонента заключается в том, что на многих динамических HTML страницах изменяются только отдельные фрагменты, основная же часть страницы остается неизменной. Шаблоном для компонента TPageProducer может служить обычная HTML-страница, в которую добавлены специальные тэги, невидимые для броузера. Формат тэга имеет следующий вид:

Шаблон может быть задан в свойстве HTMLDoc (в виде набора строк) или в свойстве HTMLFile (как имя файла). Для получения HTML страницы, построенной на основе шаблона, никаких специальных команд вызывать не нужно. Необходимо лишь прочитать свойство Content компонента TPageProducer. При этом функция, лежащая в основе свойства Content, анализирует заданный шаблон и всякий раз, когда в шаблоне встречается тэг, описанный выше, вызывает обработчик события OnHTMLTag, которому передается информация о тэге, вызвавшем событие. Обработчик события OnHTMLTag обычно возвращает строку, которой следует заменить соответствующий тэг в готовой странице. Таким образом, при обращении к свойству content возвращается строка HTML команд, в которой прозрачные тэги уже заменены динамическими значениями. При использовании компонента TPageProducer, обработчик события OnAction, возвращающий клиенту динамическую страницу, мог бы выглядеть следующим образом:

Код выглядит очень просто, однако все можно упростить еще больше. Если все, что нужно сделать в ответ на запрос, это передать страницу, созданную компонентом-генератором контента, можно вообще обойтись без обработчика OnAction. Достаточно присвоить свойству Producer соответствующего объекта TWebActionItem ссылку на компонент-генератор.

Специально для отображения содержимого баз данных в Kylix и Delphi существуют еще три компонента-генератора Web-страниц: TDataSetTableProducer, TSQLQueryTableProducer и TDataSetPageProducer.

Компонент TDataSetTableProducer генерирует HTML страницу, на которой записи из базы данных отображаются в виде таблицы. Для того, чтобы связать компонент TDataSetTableProducer с базой данных, необходимо указать соответствующее значение в свойстве DataSet. HTML-страница генерируется при обращении к свойству Content, также, как и в случае с TPageProducer. Компонент TDataSetTableProducer обладает множеством свойств, позволяющих задать различные элементы и внешний вид генерируемой страницы. Событие OnFormatCell, возникающее в процессе генерации страницы, позволяет динамически форматировать отдельные ячейки создаваемой таблицы.

Страница, созданная компонентом TDataSetTableProducer

TSQLQueryTableProducer выполняет те же функции, что и TDataSetTableProducer с тем отличием, что TSQLQueryTableProducer работает с SQL запросами к базам данных, содержащими параметры, что позволяет не отображать всю таблицу целиком, а производить выборку данных на основе некоторого признака. Источником данных для компонента TSQLQueryTableProducer является компонент TSQLQuery, на который должно указывать свойство TSQLQueryTableProducer.Query. Примеры использования компонентов TDataSetTableProducer и TSQLQueryTableProducer можно видеть в приложении frenchwines. Компонент TDataSetPageProducer позволяет создавать Web-страницу, содержащую информацию из одной (текущей) записи базы данных.

Разделяемые модули для сервера Apache.

Рассмотренные в предыдущей части приложения используют универсальный интерфейс CGI и могут работать совместно с любым Web-сервером. Web-сервер Apache позволяет также использовать модули, обладающие более широкой функциональностью. Модули могут быть скомпилированы как часть ядра Apache или же реализованы в виде разделяемых библиотек. Borland Kylix позволяет создавать только модули в виде разделяемых библиотек. Для того, чтобы сервер Apache мог подключать разделяемые библиотеки, необходимо пересобрать ядро сервера, установив опцию, разрешающую загрузку разделяемых модулей. Для пересборки ядра вам потребуются исходные тексты apache (скачать их можно с www.apache.org ) . Распакуйте архив дистрибутива и в коневом каталоге дистрибутива создайте файл config.status, содержащий следующий текст:

Далее этому файлу следует присвоить статус исполнимого:

chmod 755 config.status

запускаем созданный скрипт:

Теперь у нас есть версия Apache, поддерживающая разделяемые модули. Для того, чтобы установить сервер автоматически, необходимо в режиме root дать команду

Учтите при этом, что после выполнения этой команды новая версия Apache может быть установлена в каталог, отличный от того, в который она была установлена ранее. Возможно, вам придется отредактировать файлы сценариев запуска и файл httpd.conf.

Если Apache был установлен в каталог /usr/local/apache/, то для запуска сервера вручную можно воспользоваться командой:

а для остановки:

Теперь можно перейти к написанию простейшего модуля. Для создания заготовки модуля Apache в Kylix в окне New выберите элемент Web Server Application и в открывшемся диалоговом окне – пункт Apache shared module (DSO). Kylix создаст новый проект и в нем Web-модуль, аналогичный Web-модулю CGI-приложения. Разработка модулей для Apache практически аналогична разработке CGI-приложений. Сохраните ваш модуль под именем apachedemo. Создайте новое действие (при помощи свойства Actions объекта TWebModule1 и назначьте следующий обработчик событию OnAction созданного объекта-действия:

Откройте окно исходного текста проекта (Project|View Source) и отредактируйте текст, так чтобы он выглядел следующим образом:

Значения переменных ModuleName и ContentType необходимы серверу Apache для идентификации модуля.


Модуль для сервера готов! Скомпилируйте проект. В результате компиляции должен быть создан файл libapachedemo.so. Скопируйте этот файл в каталог разделяемых модулей сервера Apache (если сервер был установлен в каталог /usr/local/apache/, каталогом разделяемых модулей будет /usr/local/apache/libexec. Далее внесите следующие строки в файл httpd.conf:

LoadModule hello_module libexec/libHelloModule.so

SetHandler hello-handler

После директивы LoadModule следует имя модуля (указанное в директиве exports библиотеки) и путь к файлу, в котором размещен модуль. Команда Location позволяет задать URL, соответствующую обработчику hello-handler. Для того, чтобы проверить работу модуля, перезапустите Web-сервер и в окне броузера наберите:

Теперь рассмотрим более интересный пример. Допустим, на вашем Web-сервере размещены файлы с исходными текстами Kylix-программ (файлы *.pas и *.dpr) и вы хотите, чтобы пользователям эти файлы передавались не в текстовом формате, а в формате HTML, с разметкой синтаксиса, характерной для Delphi и Kylix. Конечно, эту проблему можно решить, конвертируя все файлы исходных текстов в формат HTML перед размещением их на сервере, но мы пойдем другим путем. Файлы исходных текстов размещаются на сервере в обычном текстовом формате, а специальный модуль сервера Apache будет конвертировать их в формат HTML “налету”, перед посылкой клиенту. Исходный текст модуля находится здесь. Текстовый файл reserved содержит список зарезервированных слов (которые выделяются жирным шрифтом). Скопируйте этот файл в какой-нибудь каталог (например /usr/local/apache/libexec/) и укажите путь к этому файлу в константе ReservedPath в файле main.pas. Скомпилируйте проект и скопируйте полученную библиотеку libpas2html.so в каталог libexec. В файл httpd.conf добавьте следующие строки:

LoadModule pas2html_module libexec/libpas2html.so
AddType text/html .pas
AddHandler pas2html-handler .pas
AddType text/html .dpr
AddHandler pas2html-handler .dpr

После этого следует перезапустить Web-сервер. Теперь все файлы с расширениями .pas и .dpr, находящиеся в Web-подкаталогах, будут автоматически конвертироваться в формат HTML перед посылкой клиенту.

Статья и примеры программ © 2001 Андрей Наумович Боровский. Воспроизведение возможно только с разрешения автора.

Проекты Логинова Дмитрия

Статья ориентирована на начинающих Web-программистов, а также на тех, кто хочет ознакомиться в возможностями Delphi, касающихся разработки Web-приложений. Под термином «Web-приложение» я подразумеваю приложение HTTP-сервера (Apache, IIS и др.). В статье будут рассмотрены возможности Delphi 7 Enterprise. Полагаю, что все сказанное здесь будет верно и для Delphi 6 и для Delphi 2006 и для Delphi 2007.

Необходимо в начале разработки решить вопрос выбора HTTP-сервера, и выбрать модель построения вашего приложения. В настоящее время наибольшее распространение получили 2 HTTP-сервера: Internet Information Server (Services) (ISS) от Microsoft и HTTP-сервер (демон, служба) Apache. Мне приходилось работать с IIS на WinXP. IIS по умолчанию не был установлен. Для установки я выбрал Пуск / Настройка / Панель управления / Установка и удаление программ / Установка компонентов Windows / Internet Information Services. Программа установки потребовала диск с ОС Windows, и с помощью него я завершил установку.

После установки IIS требуется настроить виртуальный каталог для вашего сайта. Для этого нужно щелкнуть правой кнопкой мыши на иконке «Мой компьютер», выбрать «Управление», развернуть узлы «Службы и приложения», «Internet Information Services», «Веб-узлы». Щелкаем правой кнопкой на «Веб-узел по умолчанию» и выбираем «Создать / Виртуальный каталог», жмем «Далее», задаем псевдоним виртуального каталога «webtest» и жмем «Далее», выбираем каталог, в котором будут располагаться файлы нашего сайта (имя сайта мы только что указали — «webtest»). Укажем каталог «c:\inetpub\webtestdir» (предварительно его следует создать) и щелкаем «Далее», после этого задаем права доступа (сейчас я оставил все как есть, но если сайт работает с помощью ISAPI (DLL-библиотека) или CGI (PHP, Perl, CGI, EXE и т.д.), то нужно установить флаг «выполнение (например приложений ISAPI или CGI)», а также настроить параметр «Анонимный доступ». Жмем «Далее», затем «Готово». Дальше развернем узел «Веб-узел по умолчанию», и увидим, что там появился пункт «webtest». Щелкнем на нем провой кнопкой мыши и выберем пункт «Свойства». Откроется окно с множеством вкладок, позволяющее настроить все необходимые параметры для нашего сайта. Теперь убедимся, что IIS работает. Создадим в каталоге «c:\inetpub\webtestdir» файл index.htm (я просто создал такой файл с помощью блокнота, и скопировал в него содержимое первой попавшей под руку интернет-страницы (у вас под рукой находится то, что вы в данный момент читаете :-)). Сохраните файл index.htm, и в адресной строке Web-браузера наберите «http://localhost/webtest/». Страница открылась? Замечательно! IIS работает!
Сказанное верно для версии IIS под WinXP. Для других Windows этапы установки и настройки могут отличаться.

Создание простейшего CGI-приложения

Нам удалось настроить IIS на работу со статическими страницами. Теперь настало время рассмотреть технологию CGI. В простейшем случае CGI — это консольное приложение. Практически все современные языки программирования позволяют разрабатывать консольные приложения, а все популярные операционные системы позволяют такие приложения запускать. Запустите Delphi и выберите меню File / New / Other / Console Application. Сохраните файл проекта под именем cgitest.dpr. Замените содержимое файла cgitest.dpr на следующее:

Первой строкой приложение должно возвращать «Content-Type: text/html», а следующей должна следовать пустая строка (WriteLn;). Директива определяет расширение исполняемого файла. Наш файл будет называться «cgitest.cgi». Укажите в опциях проекта (Project / Options / Directories/Conditionals / Output directory) каталог, в который будет размещен файл «cgitest.cgi». Укажите каталог «c:\inetpub\webtestdir\». Выполните компиляцию проекта и убедитесь, что файл «c:\inetpub\webtestdir\cgitest.cgi» присутствует.

В настройках IIS (см. выше) откройте свойства узла «webtest», перейдите на страницу «Виртуальный каталог». В поле «Разрешен запуск» выберите «Сценарии и исполняемые файлы». В поле «Защита» я на всякий случай выбрал пункт «Низкая (Процесс ISS)». Перейдите на вкладку «Безопасность каталога» и щелкните «Изменить. «. Появится окно «Методы проверки подлинности». В поле «Анонимный доступ» вы увидите имя пользователя, под которым IIS будет запускать CGI-приложения. Сейчас там вы видите пользователя «IUSR_ComputerName». Эта учетная запись была создана автоматически при установке службы IIS. Ее тип: Гостевая учетная запись интернета. Ее описание: Встроенная учетная запись для анонимного доступа к IIS. Она относится к группе пользователей «Гости». Ей запрещен доступ к системным каталогам и к разделу HKEY_LOCAL_MACHINE системного реестра (вернее доступ есть, но только на чтение). В некоторых случаях это ограничение оказывается недопустимым, и приходится менять настройки анонимного доступа. Вместо пользователя «IUSR_ComputerName» я выбрал пользователя «Администратор». Предварительно мне пришлось добавить пароль для входа пользователя «Администратор». Сперва я из панели управления открыл «Учетные записи пользователей», щелкнул «Изменение входа пользователей в систему» и снял флаг «Использовать страницу приветствия». Далее щелкнул Пуск / Выход из системы / Смена пользователя, вошел под пользователем «Администратор», открыл окно «Учетные записи пользователей», щелкнул на учетной записи «Администратор», выбрал «Создание пароля» и задал пароль. Здесь же я вновь выбрал «Изменение входа пользователей в систему» и вернул флаг «Использовать страницу приветствия». Затем я вновь вошел под своей учетной записью, открыл окно свойств узла «webtest» и в окне «Методы проверки подлинности» выбрал пользователя «Администратор». Для этого в поле «Анонимный доступ» я щелкнул Обзор / Дополнительно / Поиск, выбрал из списка пункт «Администратор», щелкнул 3 раза «ОК», затем «Применить». С настройкой учетной у меня проблем не возникло, т.к. компьютер находится в «рабочей группе», а я вхожу в группу «Администраторы». Кстати, вместо пользователя «Администратор» вы могли бы выбрать любого другого пользователя с аналогичными правами, только предварительно следует создать для него пароль.

Теперь введите в адресной строке Web-браузера текст «http://localhost/webtest/cgitest.cgi/». У вас откроется HTTP-страница с текстом:

Наше приложение уже является полноценным приложением HTTP-сервера, несмотря на число строк кода (всего 4 функциональных строки кода), и размер выходного файла (всего 15 Кбайт). Огромное число Internet-сайтов построено именно по этой технологии, т.е. с помощью той или иной среды программирования создается консольное приложение, функциональность которого наращивается по мере необходимости. Кстати, различные интерпретаторы (Perl, PHP и др.) тоже являются CGI-приложениями (только они еще выполняют задачу по интерпретации скриптов).

При размещении Web-сайта на собственном сервере у вас есть выбор при разработке CGI-приложения. Вы можете разработать полноценное консольное CGI приложение, и добавить в него любою функциональность. Оно может иметь доступ к любым ресурсам серверного компьютера, может им управлять. Также вы можете разработать свое приложение в форме PHP- или Perl-скрипта, но в этом случае приложение сможет выполнить только действия, разрешенные интерпретатором. Например, интерпретатор PHP может разрешить доступ к любому файлу из директории, в которой расположен файл скрипта, но при этом запретить доступ к любой другой директории. В плане безопасности этот подход является более удобным, поэтому, если вы хотите разместить свой сайт на каком-нибудь интернет-сервере, предоставляющим услуги (платные или бесплатные) по размещению пользовательских сайтов, то HTTP-сервер скорее всего будет настроен лишь на работу со скриптовыми сайтами, а консольные CGI-приложения работать не будут. В этом случае изучайте скриптовые языки :). Однако нынешняя тенденция, при которой все больше и больше пользователей Интернета размещают Web-сервер на собственном компьютере, делает консольные CGI-приложения очень популярными.

Модели Web-приложений и их особенности

Технология WebBroker позволяет создавать кроссплатформенные приложения для HTTP-серверов с использованием технологий ISAPI/NSAPI, CGI executable, Apache Shared Module, а также для отладки (Web App Debugger Executable). Причем эта технология позволяет с наименьшими усилиями конвертировать проект из одного типа в другой. Например, при разработке Web-приложения использовался тип Web App Debugger Executable (позволяет использовать отладчик Delphi для трассировки Web-приложений). После окончания разработки можно преобразовать приложение в ISAPI/NSAPI, CGI executable или Apache Shared Module. Процесс преобразования не отнимет много времени, т.к. база приложения, обеспеченная компонентами WebBroker, при конвертировании не затрагивается.

Отметим особенности использования той или иной технологии. Технология CGI позволяет обновлять файлы скриптов либо исполняемых модулей без перезапуска HTTP-сервера. Достаточно удалить старый файл и скопировать на его место обновленный файл. CGI — самый дешевый способ разработки Web-приложений. Многие бесплатные программные среды позволяют создавать консольные CGI-приложения. Технологии ISAPI/NSAPI и Apache Shared Module отличаются тем, что ISAPI/NSAPI работает с ISS, а Apache Shared Module работает с Apache. И то и другое — динамические DLL-библиотеки (для Apache обычно используется расширение *.SO). Apache грузит все модули при своем запуске и выгружает их при своем завершении. Для обновления модуля требуется остановить работу демона Apache, удалить старый файл модуля и скопировать на его место новый файл. ISS грузит DLL-модули только при обращении к ним (из браузера), а выгружает их при своем завершении, однако в окне свойств сайта IIS есть кнопка «Выгрузить», позволяющая выгрузить DLL-модуль без завершения работы службы IIS. При использовании DLL (SO) — модулей очень легко можно нарушить работоспособность HTTP-сервера, т.к. модуль работает в адресном пространстве сервера (однако если HTTP-сервер создает дополнительные процессы для обработки клиентских запросов, то нарушить его работоспособность будет куда сложнее). При использовании CGI ваше приложение и HTTP-сервер работают в разных процессах, поэтому ошибки вашего приложения не влияют на работоспособность HTTP-сервера. При каждом клиентском запросе HTTP-сервер запускает CGI-приложение, и в качестве параметров передает данные клиентского запроса. После обработки запроса CGI-приложение отдает результаты обратно HTTP-серверу и завершает свою работу (это относится и к PHP и к Perl). В один и тот же момент времени одно и то же CGI-приложение может обрабатывать несколько клиентских запросов. Это означает, что HTTP-сервер запустит несколько копий CGI-приложения (столько, сколько нужно). Это нужно учитывать, если CGI-приложение использует глобальные ресурсы (например файлы). Доступ к таким ресурсам следует синхронизировать (например, с помощью мьютексов) (при использовании скриптов такой проблемы нет, т.к. интерпретатор сам выполняет необходимую синхронизацию). Если Web-приложение реализовано в виде DLL (SO) — модуля (по технологии WebBroker), то при обработке клиентского запроса ядро WebBroker создает объект TWebModule. Этот объект отвечает за обработку запросов и выдачу результата. После окончания обработки запроса DLL-библиотека не выгружается, а WebBroker не спешит удалять созданный ранее объект TWebModule. Тот же самый объект будет использован при обработке следующих запросов (это делается в целях улучшения производительности Web-приложения, при этом уменьшается время отклика на клиентские запросы). Это нужно иметь ввиду. Нужно перед обработкой каждого запроса выполнять инициализацию глобальных объектов (переменных), и объектов (переменных), которые являются полями объекта TWebModule («выполнять» естественно при необходимости). Кроме того, что объекты TWebModule не удаляются после обработки запроса, они при каждом запросе могут работать в разных потоках (threads). Это тоже нужно иметь ввиду. Если ваше Web-приложение использует функциональность какого-либо COM-сервера (или DCOM-сервера), то вы перед началом работы с COM/DCOM осуществляете вызов ActiveX.CoInitialize(nil), а по окончании работы вызываете ActiveX.CoUninitialize, причем эти функции привязаны к тому потоку, из которого они вызываются. Для корректной работы COM/DCOM может потребоваться каждый раз при обработке клиентских запросов осуществлять вызов ActiveX.CoInitialize(nil), создать необходимые COM-объекты, а после окончания работы с COM/DCOM нужно будет удалить все созданные COM-объекты и вызвать функцию ActiveX.CoUninitialize. Можно поступить иначе — создать отдельный поток, который будет работать на протяжении всего времени работы Web-приложения, и всю работу с COM/DCOM выполнять именно в этом потоке (правда это может оказаться более опасным, т.к. при неумелой работе с дополнительными потоками вы рискуете повесить не только ваше Web-приложение, но и весь HTTP-сервер).

Создание CGI-приложения по технологии WebBroker

В данной программе создано 3 действия (actions) с названиями acDefault, acMain, acRegForm. Действия соответствуют страницам, которые запрашивает пользователь. Каждое действие имеет обработчик OnAction, который вызывается в нужный момент ядром WebBroker. Если пользователь ввел адрес «http://localhost/webtest/cgitest2.cgi/main», то WebBroker вызовет обработчик действия acMain: WebModule1acMainAction. Для этого WebBroker выполнит разбор строки запроса, извлечет из нее имя страницы «/main», затем в цикле выполнит перебор всех действий, пока не найдет действие, у которого PathInfo = «/main». Именно его обработчик OnAction и будет вызван. Для того, чтобы добавить новое действие, следует дважды щелкнуть на Web-модуле, в результате чего появится окно со списком всех действий, в котором нужно добавить необходимые действия. Ниже представлено содержимое моего Web-модуля в текстовом виде:

Также, как и в предыдущем примере, настройте в опциях проекта параметр Output directory (установите «c:\inetpub\webtestdir\»), и измените расширение с помощью команды <$E cgi>. Выполните компиляцию проекта. Убедитесь, что сайт работает (для этого введите в браузере адрес «http://localhost/webtest/cgitest2.cgi/»). Сперва вы окажетесь на главной странице, и увидите приветствие «Добро пожаловать, неизвестный пользователь!». Щелкните на ссылке, которая находится справа от предложения «Вы еще не зарегистрированы?», и попадете на страницу регистрации. Введите свое имя и нажмите «Принять». В результате вы вновь попадете на главную страницу, и увидете вместо «неизвестный пользователь» свое имя. Попробуйте прямо в адресной строке вручную указать «левую» страницу, например «main1». Вы окажетесь на странице с текстом «Запрашиваемая страница не найдена». Таким образом сделано все, что было нами запланировано.

Установка CGI-приложения на сервер Apache

В данный момент у вас запущен HTTP-сервер IIS. Перед запуском Apache следует остановить данную службу, иначе Apache не сможет прослушивать стандартный порт 80, т.к. этот порт уже занят службой IIS. Для останова IIS нужно щелкнуть правой кнопкой мыши на иконке «Мой компьютер», выбрать «Управление», развернуть узел «Службы и приложения», щелкнуть на пункте «Службы», найти службу «Веб-публикации», щелкнуть на ней правой кнопкой мыши и выбрать «Стоп». При необходимости вы сможете запустить ISS, для этого нужно будет запустить службу «Веб-публикации».

Вот теперь можно запустить Apache. Если у вас он не установлен, то установите. У меня установлен Apache 1.3, но и с более новыми версиями, думаю, сложностей не будет. Теперь запустите Apache. Его можно запустить либо как службу, либо как консольное приложение. Последний вариант более предпочтителен, т.к. в окно консоли выводятся все ошибки, возникшие при работе Apache. Останов Apache также проще (быстрее) производить в окне консоли (Ctrl+C). После того, как Apache был запущен, скопируйте файл «c:\Inetpub\webtestdir\cgitest2.cgi» в каталог cgi-bin\. У меня это: «c:\Program Files\Apache Group\Apache\cgi-bin\». Введите в браузере адрес «http://localhost/cgi-bin/cgitest2.cgi/». Должна открыться главная страница сайта. Выполните регистрацию (она требуется повторно, поскольку адрес сайта теперь другой), и убедитесь, что ваше имя красуется на главной странице сайта. И на IIS и на Apache сайт должен работать одинаково. При желании вы можете сделать так, чтобы адрес сайта для Apache совпадал с адресом сайта для IIS. Это потребует небольшой корректировки в файле конфигурации Apache «httpd.conf».

Как видите, для запуска CGI приложения в случае с Apache не потребовалось ровно никаких настроек.

Разработка ISAPI-приложения для Internet Information Services

Материал из раздела Модели Web-приложений и их особенности дает общее представление о технологии ISAPI/NSAPI. В данном разделе мы выполним конвертацию проекта cgitest2.dpr из CGI в ISAPI/NSAPI. В результате будет создан DLL-модуль, который будет выполнять те же задачи, что и cgitest2.cgi. Запустите Delphi и выберите меню File / New / Other / Web Server Application. Выберите модель Web-приложения «ISAPI/NSAPI Dynamic Link Library» и нажмите «ОК». Сохраните все файлы проекта в новом каталоге. Основной файл проекта назовите isapitest.dpr, а pas-файл назовите «webunit.pas». Теперь из каталога с файлами проекта cgitest2.dpr скопируйте файлы webunit.pas и webunit.dfm в каталог с проектом isapitest.dpr. Файловый менеджер запросит подтверждение на замену файла (нажать «ОК»). Укажите в опциях проекта (Project / Options / Directories/Conditionals / Output directory) каталог, в который будет размещен файл «isapitest.dll». Укажите каталог «c:\inetpub\webtestdir\». Выполните компиляцию проекта и убедитесь, что файл «c:\inetpub\webtestdir\isapitest.dll» присутствует. Запустите службу IIS (перед этим остановите HTTP-сервер Apache, если он запущен). Убедитесь, что сайт работает (для этого введите в браузере адрес «http://localhost/webtest/isapitest.dll/»). Логика работы сайта должна быть абсолютно такой же, как и предыдущих примерах. Как видите, процесс преобразования приложения оказался очень простым. Естественно, нужно учитывать, что если раньше мы работали с автономным CGI-приложением (фактически EXE, только с измененным расширением), то теперь имеем дело с DLL-библиотекой, работающей в адресном пространстве приложения «c:\WINDOWS\system32\inetsrv\inetinfo.exe», и ошибки, допущенные разработчиком в DLL-библиотеке могут привести к ошибкам в работе службы IIS. Сложнее стала ситуация с обновлением DLL-модулей. Предварительно нужно выгрузить DLL-модуль с помощью кнопки «Выгрузить» из окна настроек виртуального каталога IIS. Не стоит думать, что эта же DLL будет работать с HTTP-сервером Apache. У Apache свой интерфейс взаимодействия с DLL (SO), а также требуется внести дополнительные настройки в файл конфигурации httpd.conf.

Разработка Apache Shared Module

Данная модель приложения эквивалентна ISAPI/NSAPI, но работает не с IIS, а с HTTP-сервером Apache. В данном разделе мы выполним конвертацию проекта cgitest2.dpr из CGI в Apache Shared Module. В результате будет создан DLL-модуль, который будет выполнять те же задачи, что и cgitest2.cgi. Запустите Delphi и выберите меню File / New / Other / Web Server Application. Выберите модель Web-приложения «Apache 1.x Shared Module» (наличие данного пункта гарантированно имеется в Delphi 7, однако в более поздних версиях пункт может быть убран) и нажмите «ОК». Сохраните все файлы проекта в новом каталоге. Основной файл проекта назовите apsmtest.dpr, а pas-файл назовате «webunit.pas». Теперь из каталога с файлами проекта cgitest2.dpr скопируйте файлы webunit.pas и webunit.dfm в каталог с проектом apsmtest.dpr. Файловый менеджер запросит подтверждение на замену файла (нажать «ОК»). Укажите в опциях проекта (Project / Options / Directories/Conditionals / Output directory) каталог, в который будет размещен файл «apsmtest.dll». Укажите каталог «c:\Program Files\Apache Group\Apache\modules\». Откройте файл проекта (Project / View Source). Там расположен код:

Измените «Project1_module» на «apsmtest_module»;

Добавьте после строки Application.Initialize следующий код:

Выполните компиляцию проекта и убедитесь, что файл «c:\Program Files\Apache Group\Apache\modules\apsmtest.dll» присутствует. Внесем изменения в конфигурационный файл сервера Apache. Откроем с помощью блокнота файл «c:\Program Files\Apache Group\Apache\conf\httpd.conf», найдем раздел «Dynamic Shared Object (DSO) Support» и добавим в конец раздела (перед «Section 2: ‘Main’ server configuration») следующее описание:

Здесь apsmtest_module (после LoadModule) один в один должен соответствовать тому, что мы задали в директиве exports (в файле apsmtest.dpr). modules/apsmtest.dll определяет имя библиотеки, которая будет загружаться при запуске сервера Apache. Пути можно задавать относительно конфигурационного параметра ServerRoot. С помощью директивы мы определяем, что Apache будет обращаться к библиотеке «apsmtest.dll» при указании пользователем http-адреса: «http://ServerName/apachetest/». Т.е. пользователь вообще знать не будет, что существует какая-то библиотека «apsmtest.dll». Он просто вводит псевдоним «/apachetest/» и получает желаемый результат. Значение параметра SetHandler должно совпадать со значением переменной ContentType, которое мы задали в файле apsmtest.dpr. Можно было не указывать значение переменной ContentType. В этом случае в SetHandler нельзя будет ничего другого задавать, кроме apsmtest-handler (apsmtest — это имя библиотеки без расширения).

Запустите HTTP-сервер Apache (перед этим остановите службу IIS, если она запущена). Убедитесь, что сайт работает (для этого введите в браузере адрес «http://localhost/apachetest/»). Логика работы сайта должна быть абсолютно такой же, как и предыдущих примерах.

Процесс преобразования Web-приложения из CGI в Apache Shared Module оказался немного сложнее, чем в случае с ISAPI/NSAPI. Однако код приложения практически не изменился. Был немного изменен файл apsmtest.dpr. Кое что пришлось добавить в файл httpd.conf. Но это, согласитесь, копейки. Благодаря WebBroker нам не нужно тратить время на преобразование Web-приложения из одной модели в другую.

Разработка CGI-приложения для публикации базы данных

Мы разработаем простейшее CGI-приложение для публикации базы данных. Сайт будет состоять из двух страниц. На первой странице «main» будут отображены записи из таблицы «country.db» с кнопками «Добавить», «Изменить», «Удалить». На второй странице «editform» будет расположена форма для редактирования полей указанной либо добавляемой записи. Если пользователь хочет удалить выбранную запись, то программа должна запросить у него подтверждение. Физически на странице «editform» модификация базы данных выполняется не будет. Эта форма служит для сбора всех необходимых данных. На ней будут расположены кнопки «ОК» и «Отмена». Когда пользователь нажмет на любую из этих кнопок, будет вновь открыта страница «main», но процедура формирования страницы «main» предварительно внесет необходимые изменения, если пользователь на странице «editform» нажал «ОК».

Код Web-модуля разработанной программы смотрите здесь.

Архив приложения вы можете скачать здесь.

Я установил CGI-приложение в каталог /cgi-bin/ сервера Apache. Для входа на сайт использую адрес «http://localhost/cgi-bin/cgidb.cgi/main». Для добавления записи требуется нажать «Добавить», затем в форме ввода указать значения полей и нажать «ОК». Для изменения записи следует выбрать запись (использовать radiobutton в правой колонке), нажать кнопку «Изменить», указать значения полей и нажать «ОК». Для удаления записи следует выбрать запись, нажать «Удалить» и нажать «ОК» в ответ на запрос подтверждения удаления записи. Все функционирует согласно требованиям к задаче!


Приложение должно точно также работать и под IIS (если конечно вы не забыли выполнить настройки анонимного доступа согласно инструкции). Убедитесь, что все работает как следует.

Модуль извлечения файлов из POST-запроса

Вы можете в HTML-тэг ‘ );

Данная HTML-форма позволяет отправить на сервер любой файл. В одной форме вы можете отправить на сервер сразу несколько файлов и значений элементов ввода (в данном примере на сервер будет отправлен выбранный пользователем файл и текстовое описание к нему).

Максимальный размер файла (точнее — длина POST-запроса), передаваемого на сервер, определается опциями запущенного HTTP-сервера. Если длина POST-запроса не ограничивается, то пользователь можеть отправить на ваш сайт слишком большой файл, и, обрабатывая такой файл, ваше приложение зависнет, либо завершит работу с ошибкой.

Библиотека WebBroker не предоставляет средств для разбора POST-запросов типа «multipart/form-data». Для разбора таких запросов используйте модуль MsMultipartParser. Пример работы с модулем:

Алгоритм передачи файла браузеру

Мы рассмотрели процесс передачи файла от браузера к серверу. При этом в одном-единственном POST-запросе можно передать как один, так и множество файлов.

Теперь рассмотрим особенности обратного процесса — передачи файла от сервера к браузеру. Каждый день Вы бываете в интернете, при этом скачиваете различные программы, архивы, документы и т.д. Для этого Вы жмете ссылку «Скачать файл», и через секунду браузер открывает окно загрузки, и Вы указываете, как браузер с этим документом должен поступить (запустить / сохранить на диск / скачать с помощью специализированной программы закачки и т.п.). При нажатии ссылки «Скачать файл» к вам загружается требуемый файл.

Это было очень упрощенное описание, Вы все это знаете с первого дня работы в интернете. А теперь перейдем к техническим деталям. Для наглядности приведем список некоторых особенностей этого процесса:

  • При нажатии ссылки «Загрузить файл» браузер передает на сервер GET-запрос и при этом браузер заведомо не может знать то, какой ответ ему вернется: это может быть HTML-страница, изображение, PDF-документ, файл MP3 и т.п. Более того, о содержимом ответа заранее не знает ни HTTP-сервер, ни Web-приложение, которое подготавливает этот ответ.
  • При получении одного GET-запроса сервер может вернуть браузеру только один ответ. При скачивании файлов это означает, что сервер за один раз НЕ МОЖЕТ передать браузеру сразу несколько файлов.
  • Если в ссылке «Загрузить файл» указан статический адрес файла (например http://example.com/files/file.zip), то это, как правило (но не всегда), означает, что за передачу файла браузеру отвечает HTTP-сервер, и никакие дополнительные Web-приложения (CGI, PHP, Perl и т.п.) в этом процессе не участвуют. При этом, как правило, возможна докачка файла (все популярные HTTP-сервера (IIS, Apache и т.п.) поддерживают докачку файла).
  • Если в ссылке «Загрузить файл» указан «динамический» адрес файла (например «http://example.com/download.cgi/file.zip» или «http://example.com/download.cgi?target=file.zip» или «http://example.com/download.cgi?filenum=100» и т.п.), то за передачу файла браузеру отвечает, как правило, Web-приложение (в данном случае: download.cgi). При этом чаще всего докачка файла не поддерживается (реализация докачки требует соответствующих навыков и знаний у разработчика Web-приложений, и эти знания приходят со временем).
  • При получении файла браузер не перезагружает открытую HTML-страницу.

Вероятно Вы будете удивлены, но организовать в WebBroker передачу файла от сервера к браузеру очень просто. Если не делать докачки, то это буквально 5 строк кода. Ниже представлен пример:

Пользователь вводит в адресной строке браузера запрос «http://localhost/webtest/cgitest.cgi/download?file=ИмяФайла» и в результате сервер передает браузеру запрошенный файл, после чего браузер спрашивает у пользователя, что с этим файлом делать дальше (сохранить или открыть).

Для того, чтобы браузер не пытался отобразить содержимое файла в виде веб-страницы (кстати в интернете это распространенная ошибка), мы добавляем соответствующий заголовок:

Для того, чтобы указать браузеру имя файла, используется дополнительная строка HTTP-заголовока «Content-Disposition»:

Имя файла указывайте ТОЛЬКО латинскими буквами и БЕЗ ПРОБЕЛОВ. При необходимости выполняйте транслитерацию с русского на английский. Такое некрасивое ограничение связано с тем, что каждый браузер трактует кодировку поля filename по своему (кто в 1-байтовой кодировке ANSI, а кто в многобайтовой UTF-8). Поэтому, если Вы укажете имя файла русскими буквами в кодировке ANSI Win-1251, то Internet Explorer его отобразит правильно, а FireFox отобразит пустую строку. Если же Вы укажите русское имя файла в кодировке UTF-8 (например переконвертируете с помощью функции AnsiToUtf8()), то FireFox его отобразит правильно, а Internet Explorer покажет кракозябры. И врядли в ближайшем будущем такую проблему получится красиво решить.

Теперь несколько слов о докачке. Перед скачиванием файла браузер еще не знает тип и размер ответа. При получении и начале скачивания файла, его размер и тип становятся известны. Если в процессе скачивания файла пользователь нажмет на «паузу», а затем «возобновить», то браузер запросит у сервера лишь необходимый участок файла, т.е. те байты, которые еще не были скачаны. При этом в заголовок HTTP добавляется параметр Range. Пример такого параметра:
Range: bytes=672906-

Большинство Web-приложений в Интернете не поддерживают докачку, поэтому на такой запрос обычно они возвращают целиком весь файл, при этом браузер выдаст сообщение об ошибке.

Для правильной обработки GET-запросов, которые содержат параметр Range, Web-приложение должно проанализировать диапазон байтов и скопировать в тело ответа только байты из указанного диапазона. Если в заголовке GET-запроса указано только начало диапазона, а затем дефис, то следует вернуть участок до конца файла.

Значение параметра Range в WebBroker извлекается по-разному в зависимости от типа приложения. Для CGI (EXE) используется следующий код:
S := GetEnvironmentVariable(‘HTTP_RANGE’);
Для ISAPI (DLL) используется следующий код:
S := Request.GetFieldByName(‘Range’);

Дальнейший анализ строки и копирование требуемого участка файла в поле Response.Content не составляют особого труда.

Сжатие HTML-страницы для экономии траффика

Старайтесь ВСЕГДА сжимать подготовленные HTML-страницы перед передачей их пользователю!

Эффект от сжатия очень большой. При сжатии экономятся ресурсы сервера (сжатие отнимает ресурсов меньше, чем организация передачи клиенту большого объема текста), экономится траффик (причем как со стороны сервера, так и со стороны пользователя), существенно увеличивается скорость загрузки и отрисовки страницы в браузере (чаще всего браузер сначала загружает полностью весь сжатый HTTP-ответ, а затем в один миг осуществляет отрисовку всей HTML-страницы). Чем больше объем текстовой информации, тем больше степень сжатия. Например, HTML-страница размером 7МБ может быть сжата в 70КБ (разница — в 100 раз). Это реальный пример, но у Вас степень сжатия может отличаться в зависимости от содержимого HTML-страницы.

Сайтов с gzip сжатием в Интернете в сотни раз меньше, чем сайтов без сжатия. Зачастую Web-разработчики и не подозревают о существовании gzip-сжатия (не говоря об обычных пользователях). Попробуйте открыть с помощью Вашего браузера любую HTML-страницу. Как Вы определите, применялось ли к ней gzip-сжатие или нет? Практически никак!

А знаю 2 способа это проверить: 1 — установить браузер FireFox и дополнение к нему FireBug; 2 — установить Fiddler. О наличии gzip-сжатия свидетельствует строка Content-Encoding: gzip в заголовке HTTP-ответа.

Браузер может поддерживать gzip-сжатие, а может и не поддерживать. Если поддерживает, то в заголовке GET-запроса передается примерно такая строка:
Accept-Encoding: gzip,deflate
Вам не следует обращать внимание на deflate. Это устаревший тип сжатия. Современные браузеры поддерживают deflate-сжатие лишь для совместимости со старыми HTTP-серверами. Врядли Вы сейчас найдете браузер, который поддерживает deflate, но при этом не поддерживает gzip.

Используйте gzip-сжатие только для сжатия текстовой информации. Файлы PDF, PNG, GIF, JPEG, PDF, инсталляторы EXE и т.д. обычно уже сжаты, и поэтому их повторное сжатие не целесообразно и попусту растрачивает ресурсы сервера.

В WebBroker действия по сжатию следует осуществлять в конце обработчика WebModuleAfterDispatch. Ниже приведен пример gzip-сжатия:

На всякий случай здесь приводится также пример deflate-сжатия. Deflate-сжатие для IE6 не делается, т.к. этот браузер не может правильно распаковать данные, сжатые методом deflate, и вместо HTML-страницы отображает пустую страницу.

ZCompressStrG и ZCompressStr — это функции из модуля ZLIBEX.

Кстати Вы сейчас читаете страницу более 60КБ без gzip-сжатия :) Как только будет время — обязательно добавлю!

Выбор кодировки: WIN-1251 vs. UTF-8

WIN-1251 — это российская кодовая страница однобайтовой кодировки ANSI, в которой первые 127 символов — стандартные (латиница), а последние 128 символов — кириллица. Т.е. Ваша HTML-страница может содержать либо латинские, либо русские буквы. Вы не сможете выводить текст на других языках (ни на немецком, ни на французском, ни даже на украинском, ну а тем более на китайском).

UTF-8 — это многобайтовая кодировка, в которую включены все мировые языки. Определение «многобайтовая» означает, что разные языки могут кодироваться разным числом байтов: латиница — 1-м байтом, кириллица 2-мя байтами, различные иероглифы — 4-мя байтами. Кодировка UTF-8 совместима с Unicode, однако в Unicode любой символ кодируется фиксированным числом байтов (например, 2 байта). В принципе, с точки зрения американцев, UTF-8 и ANSI — это одно и то же. С точки зрения остальных — это совершенно разные кодировки. Используя кодировку UTF-8 Вы можете одновременно использовать на своей HTML-странице любые символы из любых языков.

Кодировка UTF-8 уже давно является стандартом для Интернета, поэтому делайте выбор в пользу UTF-8 не раздумывая!

WebBroker в Delphi 2010 имеет встроенную поддержку UTF-8. Для ее включения достаточно указать в обработчике WebModuleBeforeDispatch следующую строку:
Response.ContentType := ‘TEXT/HTML; CHARSET=UTF-8’;

В старых версиях Delphi этого недостаточно. Требуется также добавить в обработчик WebModuleAfterDispatch следующий код:

Инструментарий Web-разработчика из разряда «must have» (должен иметь)

Опишу лишь самую малость. Во-первых, эффективная Web-разработка на мой взгляд совершенно немыслима без Fiddler. Fiddler позволяет просматривать абсолютно весь HTTP-траффик между вашим браузером (а также любыми другими приложениями) и интернетом. Благодаря Fiddler многие вещи, казавшиеся раньше непонятными и сложными, становятся простыми и очевидными. Возможности встроенного поиска Fiddler позволяют за считанные секунды найти все обращения к любому хосту, а это помогает при выяснении причины заражения той или иной HTML-страницы. Если Ваша HTML-страница заражена (симптомы: куда не ткни — вылазит страница с «нежелательным» содержимым), то Вы за пять минут выясните причину: либо виноват один из счетчиков, установленным Вами на HTML-странице, либо вирус на сервере заразил Ваши скрипты, либо вирус добавил свой HTTP-фильтр на сервере и т.д.

В качестве основного браузера рекомендую FireFox, при этом обязательно должно быть установлено дополнение FireBug. FireBug — это на удивление эффективное и мощное средство для разбора кода HTML-страницы, быстрой настройки стилей, отладки Java Script и многого другого. Кроме того, FireBug осуществляет мониторинг всех HTTP-запросов, связанных с данной страницей (все же для этих целей намного лучше использовать Fiddler).

Кроме того, рекомендую установить дополнение YSlow. Мне оно помогает в тех случаях, когда требуется быстро преобразовать сжатые скрипты Java-Script в читабельный вид. Кроме того, Вы найдете в YSlow еще много полезных возможностей.


Инструменты, выручающие не только при Web-программировании, но и любом программировании, а также при исследовании работы сторонних программ: Process Monitor и Process Explorer.

Заключение

В статье показаны некоторые приемы программирования Web-приложений в Delphi. Приведены сведения по установке и настройке HTTP-серверов ISS и Apache. Уделено особое внимание разработке CGI-приложений, способных работать под управлением любого Web-сервера без необходимости перекомпиляции. Даны сведения по разработке Web-приложений по технологии ISAPI/NSAPI, а также Apache Shared Module.

Ни слова не было сказано о дополнительных компонентах WebBroker: TPageProducer, TDataSetTableProducer, TDataSetPageProducer и др. Я полагаю, читатель самостоятельно разберется со всеми этими компонентами, если будет желание.

Национальная библиотека им. Н. Э. Баумана
Bauman National Library

Персональные инструменты

CGI (Common Gateway Interface)

CGI (англ. Common Gateway Interface — «общий интерфейс шлюза») — стандарт интерфейса, используемого для связи внешней программы с веб-сервером. Программу, которая работает по такому интерфейсу совместно с веб-сервером, принято называть шлюзом, хотя многие предпочитают названия «скрипт» (сценарий) или «CGI-программа». Обычно гипертекстовые документы, извлекаемые из www (world w >[1]

Содержание

Главное назначение CGI

Обеспечение единообразного потока данных между сервером и прикладной программой, которая запускается из-под сервера. CGI определяет протокол обмена данными между сервером и программой.

  • CGI определяет порядок взаимодействия сервера с прикладной программой, в котором сервер выступает инициирующей стороной;
  • CGI определяет механизм реального обмена данными и управляющими командами в этом взаимодействии, что не определено в HTTP.

Такие понятия, как метод доступа, переменные заголовка, MIME, типы данных, заимствованы из HTTP и делают спецификацию прозрачной для тех, кто знаком с самим протоколом.

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

CGI-скрипт — программа, написанная в соответствии со спецификацией Common Gateway Interface. CGI-скрипты могут быть написаны на любом языке программирования (C, C++ (язык программирования), PASCAL, FORTRAN и т.п.) или командном языке ( shell (Операционные Системы), cshell, командный язык MS-DOS, Perl и т.п.). Скрипт может быть написан даже на языке редактора EMAC в системах Unix.

Шлюз — это CGI-скрипт, который используется для обмена данными с другими информационными ресурсами Internet или приложениями-демонами. Обычная CGI-программа запускается сервером HTTP для выполнения некоторой работы, возвращает результаты серверу и завершает свое выполнение. Шлюз выполняется точно также, только, фактически, он инициирует взаимодействие в качестве клиента с третьей программой. Если эта третья программа является сервисом Internet, например, сервер Gopher, то шлюз становится клиентом Gopher, который посылает запрос по порту Gopher, а после получения ответа пересылает его серверу HTTP. [2]

Общий шлюзовый интерфейс CGI

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

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

Веб-серверы

Веб-сервер — это сетевое приложение, обслуживающее HTTP-запросы от клиентов, обычно веб-браузеров. Веб-сервер принимает запросы и возвращает ответы, обычно вместе с HTML-страницей, изображением, файлом, медиа-потоком или другими данными. Веб-серверы — основа Всемирной паутины. С расширением спектра сетевых сервисов веб-серверы все чаще используются в качестве шлюзов для серверов приложений или сами представляют такие функции (например, Apache Tomcat).

Созданием программного обеспечения веб-серверов занимаются многие разработчики, но наибольшую популярность имеют такие программные продукты, как Apache (Apache Software Foundation), IIS (Microsoft), Google Web Server (GWS, Google Inc.) и nginx.

  • Apache — свободное программное обеспечение, распространяется под совместимой с GPL лицензией. Apache уже многие годы является лидером по распространенности во Всемирной паутине в силу своей надежности, гибкости, масштабируемости и безопасности.
  • IIS (Internet Information Services) — проприетарный набор серверов для нескольких служб Интернета, разработанный Майкрософт и распространяемый с серверными операционными системами семейства Windows. Основным компонентом IIS является веб-сервер, также поддерживаются протоколы FTP, POP3, SMTP, NNTP.
  • Google Web Server (GWS) — разработка компании Google на основе веб-сервера Apache. GWS оптимизирован для выполнения приложений сервиса Google Applications.
  • nginx [engine x]— это HTTP-сервер, совмещенный с кэширующим прокси-сервером. Разработан И. Сысоевым для компании Рамблер. Осенью 2004 года вышел первый публично доступный релиз, сейчас nginx используется на 9-12% веб-серверов. Браузеры
  • Браузер, веб-обозреватель (web-browser) — клиентское приложение для доступа к веб-серверам по протоколу HTTP и просмотра веб-страниц. Как правило браузеры дополнительно поддерживают и ряд других протоколов (например ftp, file, mms, pop3).

Первые HTTP-клиенты были консольными и работали в текстовом режиме, позволяя читать гипертекст и перемещаться по ссылкам. Сейчас консольные браузеры (такие, как lynx, w3m или links) практически не используются рядовыми посетителями веб-сайтов. Тем не менее такие браузеры весьма полезны для веб-разработчиков, так как позволяют «увидеть» веб-страницу «глазами» поискового робота.

Исторически первым браузером в современном понимании (т.е. с графическим интерфейсом и т.д.) была программа NCSA Mosaic, разработанная Марком Андерисеном и Эриком Бина. Mosaic имел довольно ограниченные возможности, но его открытый исходный код стал основой для многих последующих разработок. [3]

Принцип работы CGI

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

  1. Элемент нумерованного списка
  2. Клиент запрашивает CGI-приложение по его URI.
  3. Веб-сервер принимает запрос и устанавливает переменные окружения, через них приложению передаются данные и служебная информация.
  4. Веб-сервер перенаправляет запросы через стандартный поток ввода (stdin) на вход вызываемой программы.
  5. CGI-приложение выполняет все необходимые операции и формирует результаты в виде HTML.
  6. Сформированный гипертекст возвращается веб-серверу через стандартный поток вывода (stdout). Сообщения об ошибках передаются через stderr.
  7. Веб-сервер передает результаты запроса клиенту.

Механизмы обмена данными


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

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

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

Общие переменные окружения

  • SERVER_SOFTWARE — определяет имя и версию сервера.
  • SERVER_NAME — определяет доменное имя сервера.
  • GATEWAY_INTERFACE — определяет версию интерфейса.

Запрос-ориентированные окружения

  • SERVER_PROTOCOL — протокол сервера. Вообще говоря, CGI разрабатывалась не только для применения в www с протоколом HTTP, но и для других протоколов также, но широкое применение получила только в www.
  • SERVER_PORT — определяет порт TCP (Transmission Control Protocol) — протокол управления передачей), по которому осуществляется взаимодействие. По умолчанию для работы по HTTP используется 80 порт, но он может быть и переназначен при конфигурировании сервера.
  • REQUEST_METHOD — определяет метод доступа к информационному ресурсу. Это важнейшая переменная в CGI. Разные методы доступа используют различные механизмы передачи данных. Данная переменная может принимать значения GET, POST, HEAD и т. п.
  • PATH_INFO — передает программе путь, часть спецификации URL, в том виде, в котором она указана в клиенте. Реально это означает, что передается путь (адрес скрипта) в виде, указанном в HTML-документе.
  • PATH_TRANSLATED — то же самое, что и PATH_INFO, но только после подстановки сервером определенных в его конфигурации вставок.
  • SCRIPT_NAME — определяет адрес скрипта так, как он указан клиентом.
  • QUERY_STRING — переменная определяет содержание запроса к скрипту.

Идентификация пользователя и его машины

  • REMOTE_HOST — доменный адрес машины, с которой осуществляется запрос.
  • REMOTE_ADDR — IP-адрес запрашивающей машины.
  • AUTH_TYPE — тип идентификации пользователя. Используется в случае если скрипт защищен от несанкционированного использования.
  • REMOTE_USER — используется для идентификации пользователя.
  • REMOTE_IDENT — данная переменная порождается сервером, если он поддерживает идентификацию пользователя по протоколу RFC-931. Рекомендовано использование этой переменной для первоначального использования скрипта.

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

  • CONTENT_TYPE — определяет MIME-тип данных, передаваемых скрипту. Используя эту переменную можно одним скриптом обрабатывать различные форматы данных.
  • CONTENT_LENGTH — определяет размер данных в байтах, которые передаются скрипту. Данная переменная чрезвычайно важна при обмене данными по методу POST, т. к. нет другого способа определить размер данных, которые надо прочитать со стандартного ввода.

Возможна передача и других переменных окружения. В этом случае перед именем указывается префикс «HTTP_». Отдельный случай представляют переменные, порожденные в заголовке HTML-документа в тагах META. Они передаются в заголовке сообщения и некоторые серверы могут порождать переменные окружения из этих полей заголовка.

Опции командной строки

Командная строка используется только при запросах типа ISIN-DEX . При HTML FORMS или любых других запросах неопределенного типа командная строка не используется. Если сервер определил, что к скрипту обращаются через ISINDEX -документ, то поисковый критерий выделяется из URL и преобразуется в параметры командной строки. При этом знаком разделения параметров является символ «+». Тип запроса определяется по наличию или отсутствию символа «=» в запросе. Если этот символ есть, то запрос не является запросом ISINDEX , если символа нет, то запрос принадлежит к типу ISIN-DEX . Параметры, выделенные из запроса, помещаются в массив параметров командной строки argv. При этом после из выделения происходит преобразование всех шестнадцатеричных символов в их ASCII-коды. Если число параметров превышает ограничения, установленные в командном языке, например в shell, то формирования командной строки не происходит и данные передаются только через QUERY_STRING . Вообще говоря, следует заранее подумать об объеме данных, передаваемом скрипту и выбрать соответствующий метод доступа. Размер переменных окружения тоже ограничен, и если необходимо передавать много данных, то лучше сразу выбрать метод POST, т.е. передачу данных через стандартный ввод.

Формат стандартного ввода

Стандартный ввод используется при передаче данных в скрипт по методу POST. Объем передаваемых данных задается переменной окружения CONTENT_LENGTH , а тип данных — переменной CONTENT_TYPE . Если из HTML-формы надо передать запрос типа: a=b&b=c, то CONTENT_LENGTH =7, CONTENT_TYPE =application/x-www-form-urlencoded, а первым символом в стандартном вводе будет символ «а». Следует всегда помнить, что конец файла сервером в скрипт не передается, а поэтому завершать чтение следует по числу прочитанных символов. Позже мы разберем примеры скриптов и обсудим особенности их реализации в разных операционных системах.

Формат стандартного вывода


Стандартный вывод используется скриптом для возврата данных серверу. При этом вывод состоит из заголовка и собственно данных. Результат работы скрипта может передаваться клиенту без каких-либо преобразований со стороны сервера, если скрипт обеспечивает построение полного HTTP-заголовка, в противном случае сервер заголовок модифицирует в соответствии со спецификацией HTTP. Заголовок сообщения должен отделяться от тела сообщения пустой строкой. Обычно в скриптах указывают только три поля HTTP-заголовка: Content-type , Location , Status .

Content-type

Указывается в том случае, когда скрипт сам генерирует документ «на лету» и возвращает его клиенту. В этом случае реального документа в файловой системе сервера не остается. При использовании такого сорта скриптов следует учитывать, что не все серверы и клиенты отрабатывают так, как представляется разработчику скрипта. Так, при указании Content-type: text/html, некоторые клиенты не реализуют сканирования полученного текста на предмет наличия в нем встроенной графики. Обычно в Content-type указывают текстовые типы text/plain и text/html.

Location

Используется для переадресации. Иногда переадресация помогает преодолеть ограничения сервера или клиента на обработку встроенной графики или серверной предобработки. В этом случае скрипт создает файл на диске и указывает его адрес в Location. Сервер, таким образом, передает реально существующий файл. В последнее время серверы стали буферизовать возвращаемые клиентам данные, что приводит к решению вопросов, связанных с повторным запуском скриптов для встраивания графики и разгрузки компьютера с сервером HTTP. [4]

Области применения CGI

Наиболее частая задача, для решения которой применяется CGI — создание интерактивных страниц, содержание которых зависит от действий пользователя. Типичными примерами таких веб-страниц являются форма регистрации на сайте или форма для отправки комментария. Другая область применения CGI, остающаяся за кулисами взаимодействия с пользователем, связана со сбором и обработкой информации о клиенте: установка и чтение «cookies»; получение данных о браузере и операционной системе; подсчет количества посещений веб-страницы; мониторинг веб-трафика и т. п.

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

Важно знать, что CGI — это не язык программирования! Это простой протокол, позволяющий веб-серверу передавать данные через stdin и читать их из stdout . Поэтому, в качестве CGI-обработчика может использоваться любая серверная программа, способная работать со стандартными потоками ввода-вывода.

Преимущества CGI

Многие возможности CGI сейчас дублируются такими технологиями, как например DHTML, ActiveX или Java-апплетами. Основными преимуществами использования серверных скриптов является то, что вы можете быть уверены, что все клиенты (за редким исключением, как правило связанным с блокировкой доступа к определенным ресурсам на уровне файрвола) смогут работать с серверным приложением. Клиентские-же программы могут быть просто отключены в браузере, или вовсе не поддерживаться.

Недостатки CGI

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

Другим недостатком CGI является меньшая, по сравнению с другими решениями, защищенность веб-сервера. Неправильная настройка прав доступа к серверным ресурсам из CGI-приложения может поставить под угрозу не только работоспособность веб-сервера, но и информационную безопасность. Впрочем, любую сетевую технологию можно считать потенциально небезопасной уже по определению. [5]

Пример простейшего cgi сервера

Думаю многие знают, как работает CGI взаимодействие между клиентом и сервером: клиент получает от сервера и отдает серверу данные через стандартные stdin и stdout. Многие наверное даже сами писали CGI клиентов, ведь по сути — любой скрипт для веб-сервера это и есть CGI-клиент.
А многие ли задавались вопросом, как именно происходит эта «магия»? Каким образом стандартные функции для ввода/вывода вместо экрана взаимодействуют с сервером?

Результаты поиска ответа в сети меня не удовлетворили и я решил сам написать простейший CGI сервер, который сможет:

  • Запускать дочерний процес — CGI скрипт
  • Передавать скрипту переменные окружения и переменные командной строки
  • Принимать от скрипта ответ
  • Завершаться, когда завершится процесс клиента

Кроме этого, мне хотелось, чтобы клиент и сервер компилировались как в Windows, так и в Linux.

CGI-клиент

Начну я все-таки с самого простого и общеизвестного: опишу своего клиента для CGI сервера. Простой «hello world» меня не устроил, потому что нужно было проверить не только возможность передачи сообщений через stdout, но и корректность приема переменных окружения и сообщений из stdin.
Кроме этого чтобы убедиться, что получилось самое настоящее CGI взаимодействие, было решено написать не один, а сразу два клиента. На с++ и на python.

Пояснения к коду клиентов

Если из CGI-сервера запустить клиента на С++, то на экран выведется информация о переменных командной строки, три переменные окружения с именами «Content-Length», «VARIABLE2» и «VARIABLE3», а также все содержимое которое получено от сервера в stdin.
Если из CGI-сервера запустить клиента на Python, то на экран выведется информация о переменных окружения с именами «Content-Length», «VARIABLE2» и «VARIABLE3», а также все содержимое которое получено от сервера в stdin.

Надо отметить, что переменная окружения «Content-Length» должна быть сформирована сервером таким образом, чтобы быть числом меньше либо равным количеству байт в stdin. Это необходимо потому, что клиент никаким другим образом не может узнать данную информацию кроме как от сервера.

CGI-сервер

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

Пояснения к коду сервера

Сервер писался так, чтобы его можно было скомпилировать как в Windows, так и в Linux, поэтому первые несколько строк это кроссплатформенные определения.
Дальше в глобальных переменных задается:

  • тело запроса который будет послан скрипту (строка «===this is request body===\n»), длина сообщения запоминается в переменной strRequestHeader
  • переменные окружения в виде массива строк
  • переменные командной строки в виде массива <"./Main_Child.exe", «first argument», «second argument», 0>

При такой инициализации сервер будет взаимодействовать с процессом «./Main_Child.exe». Так я назвал скомпилированного клиента на С++.
Если в качестве переменных командной строки задать массив <«python», "./test.py", 0>, то сервер будет взаимодействовать со скриптом на питоне.

После глобальных переменных я написал кроссплатформенный вариант функции _spawnve. Если коротко — то эта функция создает процесс, память которого полностью идентична текущему процессу и передает новому процессу другие переменные командной строки и окружения.

Заканчивается сервер функцией «main», большую часть которой (как можно догадаться по английским комментариям) я взял из разных сторонних источников. Из кода этой функции видно, что «вся соль» перенаправления ввода/вывода между процессами организована с помощью «pipe» (каналов).
Механизм каналов довольно простой и стандартный, он почти одинаково реализован как в Windows так и в Linux. Чтобы связать эти два подхода, в самом начале исходника я добавил простое переопределение:

В конце функции «main» организован бесконечный цикл, в котором сервер принимает от клиента ответ и передает этот ответ на экран. Выход из цикла произойдет когда клиентский процесс завершится.

Заключение

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

CGI-сценарии

CGI-сценарии это приложения разработанные в соответствии со спецификацией CGI (Common Gateway Interface). Данная спецификация описывает формат и общие правила обмена данными между Web-сервером и внешним приложением. Для обработки потока данных от клиента к Web-серверу и формирования обратного потока из результатов работы приложения в спецификакции CGI определены следующие элементы:

  • Переменные окружения — набор переменных среды, которые заполняются сервером при запуске CGI-сценария и содержат информацию о служебных параметрах http-запроса, который инициировал запуск данного сценария;
  • Аргументы командной строки — используются для передачи CGI-сценарию входных параметров, которые передаются как часть URL. Например: http://www.site.ru/cgi-bin/prog.pl?par1=val1;
  • Стандартные потоки ввода/вывода — при передачи данных от сервера CGI-сценарию организуется взаимодействие: поток STDOUT сервера с потоком STDIN сценария, а при обратной передаче: поток STDOUT сценария взаимодействует с потоком STDIN сервера;

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

· Unix Shell (интерфейс командной строки Unix);

· Visual Basic (компилятор);

В общих чертах алгоритм разработки CGI-сценария выглядит следующим образом:

Определение метода http-запроса.


Для этого необходимо считать значение стандартной переменной среды сервера REQUEST_METHOD, в которой содержится тип http-запроса: GET, POST (например в языке С для доступа к переменным среды используется функция — getenv(«ИМЯ ПЕРЕМЕННОЙ») ).

Получение данных от сервера.

Для метода GET данные передаются как часть URL запроса. Часть URL (остаток после имени сценария), содержащая передаваемые параметры, записываются в переменную среды сервера QUERY_STRING (в данном случае действует ограничение на длину передаваемого блока данных, обычно при записи URL усекается до 255 знаков).

Для получения данных необходимо считать значение переменной среды QUERY_STRING. Например при отправке данных из формы HTML-документа на обработку сценарию-prg, http-запрос будет выглядеть так:

А переменная среды QUERY_STRING = поле1=знач1&. &полеN=значN

Для метода POST данные передаются в STDIN сценария как тело http-запроса, в переменную среды сервера CONTENT_LENGTH записывается количество символов входного потока, а в переменную CONTENT_TYPE записывается MIME-тип передаваемых данных. Для получения данных необходимо считать CONTENT_LENGTH символов из STDIN сценария. Например при отправке данных из формы HTML-документа, на обработку сценарию-prg, http-запрос будет выглядеть так:

POST http://www.site.ru/cgi-bin/prg HTTP/1.0

Декодирование полученные данных.

Для дальнейшего использования полученных данных необходимо выполнить их небольшое преобразование, поскольку в полученной последовательности все пробелы заменяются символом +, а символы с десятичным кодом более 128 заменяются на %ХХ, где ХХ-шестнадцатеричный код.

Производится выполнение основных функций CGI-сценария, это может быть операции поиска в БД, выполнение определенных расчетов на основе полученных данных, регистрация пользователя в БД, обработка почты и многое другое.

Формирование ответа в форме HTML-документа.

Производится динамическое создание HTML-документа содержащего результаты работы сценария и вывод его в STDOUT сценария. В простейшем случае формируется документ содержащий уведомление пользователя о выполнение сценария. Перед выводом в STDOUT, сценария документ необходимо снабдить MIME-заголовком и разделительной строкой (пара символов CR) отделяющей заголовок от содержимоого тела ответа. Например вот так:

Реализации вышеуказанного алгоритма для различных платформ Web-серверов могут существенно отличаться, но приведенные этапы создания сценария достаточно общие.

Дата добавления: 2015-04-19 ; просмотров: 1038 ; ЗАКАЗАТЬ НАПИСАНИЕ РАБОТЫ

Разработка cgi

Эта статья продолжает серию, посвященную программированию Интернет-приложений в Borland Kylix. На этот раз речь пойдет о CGI-приложениях и модулях сервера Apache.

CGI-приложения

Изначально протокол HTTP создавался для передачи по Сети документов в формате HTML и сопутствующей им графики, однако Web-броузеры оказались настолько удобны, что всемирная паутина очень быстро начала обрастать различными дополнительными функциями. Весьма заманчиво выглядит возможность использовать броузер клиента в качестве интерфейса для взаимодействия с удаленным приложением. Такое взаимодействие, разумеется, требует наличия механизма передачи команд и данных от клиента серверу. Для стандартизации механизма передачи команд клиента серверу был разработан стандарт CGI. В общих чертах работа CGI выглядит следующим образом: клиент загружает HTML страницу, содержащую форму и посылает серверу определенный в форме запрос (request), в котором указано действие (action) и список параметров. Действие представляет собой указатель на CGI-приложение, которое должно выполнить запрос. Например действие /cgi-bin/frenchwines указывает на приложение frenchwines. Для одного приложения можно определить несколько действий, которые идентифицируются как отдельные сетевые ресурсы: /cgi-bin/frenchwines, /cgi-bin/frenchwines/, /cgi-bin/frenchwines/welcome – это разные действия приложения frenchwines. Список параметров представляет собой перечень имен параметров и их значений. Если HTML форма использует для передачи параметров метод GET, список параметров можно увидеть в адресной строке броузера после идентификатора ресурса (он отделен от идентификатора символом ‘?’). С точки зрения протокола HTTP CGI-запрос является командой на загрузку некоторого ресурса. В ответ на запрос сервер обычно посылает клиенту HTML документ, который как правило является динамической страницей, т. е. не хранится на диске в виде файла, а генерируется приложением.

CGI–функции могут быть реализованы на сервере в двух вариантах: в форме CGI-сценариев (CGI scripts) и в виде CGI приложений. CGI приложения представляют собой исполнимые модули, вызываемые Web-сервером. Схема взаимодействия между броузером, сервером и CGI-модулем приводится на рисунке. По своей структуре CGI приложение является обычной консольной программой. Сервер передает данные CGI приложению через переменные окружения и стандартный поток ввода, а CGI приложение передает данные серверу через свой стандартный поток вывода. Сервер запускает новую копию приложения для обработки каждого запроса. По окончании обработки запроса CGI-приложение завершается .

Далее следует пример простейшего CGI приложения, написанного в Borland Kylix. Этот пример не использует специальные средства разработки CGI приложений, входящие в состав Kylix. Модуль Libc используется для того, чтобы сделать приложение более компактным. В принципе нам было бы достаточно одного модуля SysUtils.

Для того, чтобы проверить работу примера, скомпилируйте проект simplecgi.dpr (исходный текст лежит здесь) и скопируйте полученный исполнимый файл в каталог CGI-приложений Web-сервера. В Linux Mandrake этим каталогом по умолчанию является /var/www/cgi-bin/ (естественно, сам Web-сервер должен быть установлен и запущен в вашей системе). Затем откройте в броузере страницу TestCGI.html. Страница TestCGI содержит две формы для передачи параметров приложению. Одна форма использует для передачи данных метод GET, другая – метод POST.

Кроме возможности создания CGI-приложений “с нуля”, Borland Kylix располагает весьма удобными специальными средствами разработки приложений для Web-сервера. Kylix может создать для вас “заготовку” CGI-приложения. В окне New выберите элемент Web Server Application и в открывшемся диалоговом окне – пункт CGI standalone executable.

В качестве примера такого приложения мы рассмотрим программу, реализующую Web-интерфейс к базе данных Borland Interbase. Для компиляции и выполнения этого примера вам понадобится сервер баз данных Interbase (входит в комплект поставки Kylix SDE). Перед началом работы с примером Web-интерфейса базы данных, убедитесь, что серверы Web и Interbase установлены и нормально работают.

Приложение-пример (исходный текст лежит здесь) называется fenchwines и представляет собой Web-интерфейс к базе данных французских вин. (Напомню, что “Kylix” в переводе означает “винная чаша”, так что “винная” тематика вполне соответствует рассматриваемому продукту. Для правильной компиляции и запуска демонстрационного приложения необходимо выполнить следующее: скачайте архив с базой данных, распакуйте его, скопируйте файл vina.gdb в какой-нибудь каталог. В корневом каталоге http документов вашего сервера (часто это / var/www/html) создайте каталог wdb и скопируйте в него файлы wctempl.html и barrels.jpg из архива приложения. Теперь откройте приложение в среде Kylix. При помощи менеджера проекта откройте окно Web-модуля, которое связано с модулем main. В окне Web-модуля щелкните правой кнопкой мыши по компоненту SQLConnection1 и в открывшемся меню выберите пункт Edit Connection Properties. В открывшемся диалоговом окне создайте новое соединение. В качестве драйвера базы данных выберите INTERBASE. В поле Database задайте абсолютный путь к файлу vina.gdb. Убедитесь, что поля Password и User_Name содержат значения masterkey и SYSDBA соответственно. Свойство Connection компонента SQLConnection1 должно указывать на новое соединение. Далее отредактируйте свойство HTMLFile компонента PageProducer1 так, чтобы оно содержало полный путь к файлу wctempl.html. Скомпилируйте приложение frenchwines и скопируйте исполнимый файл в каталог CGI-приложений (cgi-bin). Для того, чтобы проверить работу нашего приложения в окне броузера наберите http://localhost/cgi-bin/frenchwines. При этом в окне броузера появится приветственная HTML-страница. Форма на странице позволяет выбирать вина из базы данных по происхождению и категории. Для того, чтобы отобразить все вина, содержащиеся в базе, необходимо ввести “any” в обоих полях формы.

Структура CGI-приложения очень похожа на структуру обычного приложения Kylix. Вместо объекта TApplication в Web-приложении используется объект TWebApplication, а роль класса TForm выполняет класс TWebModule. Потомок класса TWebModule является владельцем всех компонентов, используемых в Web-приложении и ему же принадлежат методы обработки событий.

Окно компонента TWebModule с дочерними компонентами

Важнейшим элементом TWebModule является список действий Actions. В этом списке хранятся объекты TWebActionItem, определяющие действия приложения. Свойство PathInfo объекта TWebActionItem позволяет задать идентификатор действия. Если свойство PathInfo содержит пустую строку, идентификатором данного действия является само имя CGI-приложения. В других случаях идентификатор действия должен предваряться символом “/”. В следующей таблице показаны примеры значений PathInfo и соответствующие им действия для приложения frenchwines, расположенного в директории /cgi-bin/.

Значение PathInfo Действие
“” /cgi-bin/frenchwines
“/” /cgi-bin/frenchwines/
“/welcome” /cgi-bin/frenchwines/welcome
/error /cgi-bin/frenchwines/error

Список Actions можно заполнить в процессе разработки приложения при помощи редактора списка. Для того, чтобы открыть окно редактора нужно в окне инспектора объектов щелкнуть по кнопке с многоточием в поле свойства Actions.

Свойство MethodType объекта TWebActionItem позволяет указать метод передачи параметров для данного действия. Метод, указанный в свойстве MethodType должен соответствовать методу, указанному в тэге FORM HTML страницы, генерирующей запрос. Значение mtAny позволяет действию обрабатывать любые запросы.

Для объекта TWebActionItem определено единственное событие – OnAction. Когда Web-сервер получает CGI-запрос, он запускает соответствующее CGI-приложение и передает ему всю необходимую информацию. В Kylix-приложении диспетчер запросов определяет, какому действию адресован запрос, и вызывает обработчик события OnAction этого действия. После выполнения обработчика OnAction приложение завершается.

Заголовок обработчика выглядит следующим образом:

type THTTPMethodEvent = procedure (Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean) of object;

Объект Request содержит данные о поступившем запросе. Свойства этого объекта позволяют получить сведения об адресе удаленной машины, программном обеспечении клиента, методе запроса и т. п. Для CGI-запроса в объекте Request передается также список параметров запроса. Список параметров хранится в свойстве ContentFields (если запрос передан посредством метода POST) или QueryFields (если использовался метод GET). Оба свойства имеют тип TStrings и содержат набор строк вида

Объект Response описывает ответные действия приложения. Текст HTML страницы, возвращаемой приложением, передается в свойстве Content объекта Response. В простейшем CGI-приложении обработчик OnAction может выглядеть следующим образом:

Рассмотрим другие примеры. В приложении frenchwines главная HTML-страница выводится при выполнении действия frenchwines/welcome. Однако, пользователь может набрать в строке броузера просто . /frenchwines или . /frenchwines/ и было бы очень удобно, если бы в этой ситуации приложение автоматически перенаправляло броузер пользователя на страницу frenchwines/welcome. Для того, чтобы приложение fenchwines выполняло такое перенаправление, в нем заданы два действия, значениями PathInfo которых являются соответственно пустая строка и символ “/”. Обоим действиям можно назначить один и тот же обработчик OnAction:

Статус-код 301 сообщает клиенту о необходимости перенаправить запрос по новому адресу. А что произойдет, если клиент пошлет запрос на выполнение действия, которое не определено в CGI-приложении, например frenchwines/querydb ? В этом случает Kylix-приложение сгенерирует исключение и Web-сервер выдаст неприятное сообщение о внутренней ошибке. Для того, чтобы обращение к неопределенному действию не приводило к исключительной ситуации, необходимо создать еще одно действие и присвоить свойству Default соответствующего объекта TWebActionItem значение True. Теперь это действие будет вызываться для всех запросов, вызывающих неопределенные действия. Обработчик события OnAction этого действия может выглядеть следующим образом:

Генераторы контента

Во всех приведенных выше примерах HTML страницы, возвращаемые сервером задавались в явном виде, путем присвоения строки HTML команд свойству Content. Очевидно, что для вывода сложных страниц с большим числом элементов такой подход непригоден. Для облегчения решения этой проблемы Kylix предоставляет несколько специальных компонентов-генераторов контента (content producers). На вкладке Internet панели компонентов Kylix раположены четыре компонента-генератора: TPageProducer, TDataSetTableProducer, TSQLQueryTableProducer и TDataSetPageProducer.

Компонент TPageProducer генерирует страницу на основе заданного шаблона. Идея этого компонента заключается в том, что на многих динамических HTML страницах изменяются только отдельные фрагменты, основная же часть страницы остается неизменной. Шаблоном для компонента TPageProducer может служить обычная HTML-страница, в которую добавлены специальные тэги, невидимые для броузера. Формат тэга имеет следующий вид:

Шаблон может быть задан в свойстве HTMLDoc (в виде набора строк) или в свойстве HTMLFile (как имя файла). Для получения HTML страницы, построенной на основе шаблона, никаких специальных команд вызывать не нужно. Необходимо лишь прочитать свойство Content компонента TPageProducer. При этом функция, лежащая в основе свойства Content, анализирует заданный шаблон и всякий раз, когда в шаблоне встречается тэг, описанный выше, вызывает обработчик события OnHTMLTag, которому передается информация о тэге, вызвавшем событие. Обработчик события OnHTMLTag обычно возвращает строку, которой следует заменить соответствующий тэг в готовой странице. Таким образом, при обращении к свойству content возвращается строка HTML команд, в которой прозрачные тэги уже заменены динамическими значениями. При использовании компонента TPageProducer, обработчик события OnAction, возвращающий клиенту динамическую страницу, мог бы выглядеть следующим образом:

Код выглядит очень просто, однако все можно упростить еще больше. Если все, что нужно сделать в ответ на запрос, это передать страницу, созданную компонентом-генератором контента, можно вообще обойтись без обработчика OnAction. Достаточно присвоить свойству Producer соответствующего объекта TWebActionItem ссылку на компонент-генератор.

Специально для отображения содержимого баз данных в Kylix и Delphi существуют еще три компонента-генератора Web-страниц: TDataSetTableProducer, TSQLQueryTableProducer и TDataSetPageProducer.

Компонент TDataSetTableProducer генерирует HTML страницу, на которой записи из базы данных отображаются в виде таблицы. Для того, чтобы связать компонент TDataSetTableProducer с базой данных, необходимо указать соответствующее значение в свойстве DataSet. HTML-страница генерируется при обращении к свойству Content, также, как и в случае с TPageProducer. Компонент TDataSetTableProducer обладает множеством свойств, позволяющих задать различные элементы и внешний вид генерируемой страницы. Событие OnFormatCell, возникающее в процессе генерации страницы, позволяет динамически форматировать отдельные ячейки создаваемой таблицы.


Страница, созданная компонентом TDataSetTableProducer

TSQLQueryTableProducer выполняет те же функции, что и TDataSetTableProducer с тем отличием, что TSQLQueryTableProducer работает с SQL запросами к базам данных, содержащими параметры, что позволяет не отображать всю таблицу целиком, а производить выборку данных на основе некоторого признака. Источником данных для компонента TSQLQueryTableProducer является компонент TSQLQuery, на который должно указывать свойство TSQLQueryTableProducer.Query. Примеры использования компонентов TDataSetTableProducer и TSQLQueryTableProducer можно видеть в приложении frenchwines. Компонент TDataSetPageProducer позволяет создавать Web-страницу, содержащую информацию из одной (текущей) записи базы данных.

Разделяемые модули для сервера Apache.

Рассмотренные в предыдущей части приложения используют универсальный интерфейс CGI и могут работать совместно с любым Web-сервером. Web-сервер Apache позволяет также использовать модули, обладающие более широкой функциональностью. Модули могут быть скомпилированы как часть ядра Apache или же реализованы в виде разделяемых библиотек. Borland Kylix позволяет создавать только модули в виде разделяемых библиотек. Для того, чтобы сервер Apache мог подключать разделяемые библиотеки, необходимо пересобрать ядро сервера, установив опцию, разрешающую загрузку разделяемых модулей. Для пересборки ядра вам потребуются исходные тексты apache (скачать их можно с www.apache.org ) . Распакуйте архив дистрибутива и в коневом каталоге дистрибутива создайте файл config.status, содержащий следующий текст:

Далее этому файлу следует присвоить статус исполнимого:

chmod 755 config.status

запускаем созданный скрипт:

Теперь у нас есть версия Apache, поддерживающая разделяемые модули. Для того, чтобы установить сервер автоматически, необходимо в режиме root дать команду

Учтите при этом, что после выполнения этой команды новая версия Apache может быть установлена в каталог, отличный от того, в который она была установлена ранее. Возможно, вам придется отредактировать файлы сценариев запуска и файл httpd.conf.

Если Apache был установлен в каталог /usr/local/apache/, то для запуска сервера вручную можно воспользоваться командой:

а для остановки:

Теперь можно перейти к написанию простейшего модуля. Для создания заготовки модуля Apache в Kylix в окне New выберите элемент Web Server Application и в открывшемся диалоговом окне – пункт Apache shared module (DSO). Kylix создаст новый проект и в нем Web-модуль, аналогичный Web-модулю CGI-приложения. Разработка модулей для Apache практически аналогична разработке CGI-приложений. Сохраните ваш модуль под именем apachedemo. Создайте новое действие (при помощи свойства Actions объекта TWebModule1 и назначьте следующий обработчик событию OnAction созданного объекта-действия:

Откройте окно исходного текста проекта (Project|View Source) и отредактируйте текст, так чтобы он выглядел следующим образом:

Значения переменных ModuleName и ContentType необходимы серверу Apache для идентификации модуля.

Модуль для сервера готов! Скомпилируйте проект. В результате компиляции должен быть создан файл libapachedemo.so. Скопируйте этот файл в каталог разделяемых модулей сервера Apache (если сервер был установлен в каталог /usr/local/apache/, каталогом разделяемых модулей будет /usr/local/apache/libexec. Далее внесите следующие строки в файл httpd.conf:

LoadModule hello_module libexec/libHelloModule.so

SetHandler hello-handler

После директивы LoadModule следует имя модуля (указанное в директиве exports библиотеки) и путь к файлу, в котором размещен модуль. Команда Location позволяет задать URL, соответствующую обработчику hello-handler. Для того, чтобы проверить работу модуля, перезапустите Web-сервер и в окне броузера наберите:

Теперь рассмотрим более интересный пример. Допустим, на вашем Web-сервере размещены файлы с исходными текстами Kylix-программ (файлы *.pas и *.dpr) и вы хотите, чтобы пользователям эти файлы передавались не в текстовом формате, а в формате HTML, с разметкой синтаксиса, характерной для Delphi и Kylix. Конечно, эту проблему можно решить, конвертируя все файлы исходных текстов в формат HTML перед размещением их на сервере, но мы пойдем другим путем. Файлы исходных текстов размещаются на сервере в обычном текстовом формате, а специальный модуль сервера Apache будет конвертировать их в формат HTML “налету”, перед посылкой клиенту. Исходный текст модуля находится здесь. Текстовый файл reserved содержит список зарезервированных слов (которые выделяются жирным шрифтом). Скопируйте этот файл в какой-нибудь каталог (например /usr/local/apache/libexec/) и укажите путь к этому файлу в константе ReservedPath в файле main.pas. Скомпилируйте проект и скопируйте полученную библиотеку libpas2html.so в каталог libexec. В файл httpd.conf добавьте следующие строки:

LoadModule pas2html_module libexec/libpas2html.so
AddType text/html .pas
AddHandler pas2html-handler .pas
AddType text/html .dpr
AddHandler pas2html-handler .dpr

После этого следует перезапустить Web-сервер. Теперь все файлы с расширениями .pas и .dpr, находящиеся в Web-подкаталогах, будут автоматически конвертироваться в формат HTML перед посылкой клиенту.

Статья и примеры программ © 2001 Андрей Наумович Боровский. Воспроизведение возможно только с разрешения автора.

CGI-сценарии

CGI-сценарии это приложения разработанные в соответствии со спецификацией CGI (Common Gateway Interface). Данная спецификация описывает формат и общие правила обмена данными между Web-сервером и внешним приложением. Для обработки потока данных от клиента к Web-серверу и формирования обратного потока из результатов работы приложения в спецификакции CGI определены следующие элементы:

  • Переменные окружения — набор переменных среды, которые заполняются сервером при запуске CGI-сценария и содержат информацию о служебных параметрах http-запроса, который инициировал запуск данного сценария;
  • Аргументы командной строки — используются для передачи CGI-сценарию входных параметров, которые передаются как часть URL. Например: http://www.site.ru/cgi-bin/prog.pl?par1=val1;
  • Стандартные потоки ввода/вывода — при передачи данных от сервера CGI-сценарию организуется взаимодействие: поток STDOUT сервера с потоком STDIN сценария, а при обратной передаче: поток STDOUT сценария взаимодействует с потоком STDIN сервера;

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

· Unix Shell (интерфейс командной строки Unix);

· Visual Basic (компилятор);

В общих чертах алгоритм разработки CGI-сценария выглядит следующим образом:

Определение метода http-запроса.

Для этого необходимо считать значение стандартной переменной среды сервера REQUEST_METHOD, в которой содержится тип http-запроса: GET, POST (например в языке С для доступа к переменным среды используется функция — getenv(«ИМЯ ПЕРЕМЕННОЙ») ).

Получение данных от сервера.

Для метода GET данные передаются как часть URL запроса. Часть URL (остаток после имени сценария), содержащая передаваемые параметры, записываются в переменную среды сервера QUERY_STRING (в данном случае действует ограничение на длину передаваемого блока данных, обычно при записи URL усекается до 255 знаков).

Для получения данных необходимо считать значение переменной среды QUERY_STRING. Например при отправке данных из формы HTML-документа на обработку сценарию-prg, http-запрос будет выглядеть так:

А переменная среды QUERY_STRING = поле1=знач1&. &полеN=значN

Для метода POST данные передаются в STDIN сценария как тело http-запроса, в переменную среды сервера CONTENT_LENGTH записывается количество символов входного потока, а в переменную CONTENT_TYPE записывается MIME-тип передаваемых данных. Для получения данных необходимо считать CONTENT_LENGTH символов из STDIN сценария. Например при отправке данных из формы HTML-документа, на обработку сценарию-prg, http-запрос будет выглядеть так:

POST http://www.site.ru/cgi-bin/prg HTTP/1.0

Декодирование полученные данных.

Для дальнейшего использования полученных данных необходимо выполнить их небольшое преобразование, поскольку в полученной последовательности все пробелы заменяются символом +, а символы с десятичным кодом более 128 заменяются на %ХХ, где ХХ-шестнадцатеричный код.

Производится выполнение основных функций CGI-сценария, это может быть операции поиска в БД, выполнение определенных расчетов на основе полученных данных, регистрация пользователя в БД, обработка почты и многое другое.

Формирование ответа в форме HTML-документа.

Производится динамическое создание HTML-документа содержащего результаты работы сценария и вывод его в STDOUT сценария. В простейшем случае формируется документ содержащий уведомление пользователя о выполнение сценария. Перед выводом в STDOUT, сценария документ необходимо снабдить MIME-заголовком и разделительной строкой (пара символов CR) отделяющей заголовок от содержимоого тела ответа. Например вот так:

Реализации вышеуказанного алгоритма для различных платформ Web-серверов могут существенно отличаться, но приведенные этапы создания сценария достаточно общие.


Дата добавления: 2015-04-19 ; просмотров: 1039 ; ЗАКАЗАТЬ НАПИСАНИЕ РАБОТЫ

Query Results

  • RealName = Петров Иван Сидорович
  • Sex = Мужской
  • Submit = Послать запрос

И на экране браузера
Query Results
You submitted the following name/value pairs:
RealName = Петров Иван Сидорович
Sex = Мужской
Submit = Послать запрос

Ниже приведен исходный текст программы post-query.

#include
#ifndef NO_STDLIB_H
#include
#elsechar *getenv();
#endif
#define MAX_ENTRIES 10000

typedef struct <
char *name;
char *val;
> entry;

char *makeword(char *line, char stop);
char *fmakeword(FILE *f, char stop, int *len);
char x2c(char *what);
void unescape_url(char *url);
void plustospace(char *str);

main(int argc, char *argv[])

<
entry entries[MAX_ENTRIES];
register int x,m=0;
int cl;
printf(«Content-type: text/html%c%c»,10,10);
if(strcmp(getenv(«REQUEST_METHOD»),»POST»))
< printf("This script should be referenced with a METHOD of POST.\n");
printf(«If you don’t understand this, see this «); printf(» forms overview.%c»,10);
exit(1);
> if(strcmp(getenv(«CONTENT_TYPE»),»application/x-www-form-urlencoded»)) exit(1);
>
cl = atoi(getenv(«CONTENT_LENGTH»));
for(x=0;cl && (!feof(stdin));x++)
unescape_url(entries[x].val);
entries[x].name = makeword(entries[x].val,’=’);
>
printf(«

Query Results

Надо отметить, что post-query не обрабатывает имена, поэтому в примере они даны на английском языке. Если Вы используете русские названия имен, то вы должны обработать имена также как и значения, т.е. заменить все символы «+» на пробелы и преобразовать шестнадцатеричные коды кириллических символов в сам символ.
Приведем также исходный текст функций используемых post-query

char *makeword (char *line, char stop) <
/* Предназначена для выделения части строки, ограниченной «стоп-символами»*/
int x = 0,y;
char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
for(x=0;((line[x]) && (line[x] != stop));x++)
word[x] = line[x];
word[x] = ‘\0’;
if(line[x]) ++x;
y=0;

while(line[y++] = line[x++]);
return word;
>

char *fmakeword (FILE *f, char stop, int *cl) <
/* Предназначена для выделения строки, ограниченной «стоп-символом» stop, из потока f длиной cl.
*/
int wsize;
char *word;
int ll;

wsize = 102400;
ll=0;
word = (char *) malloc(sizeof(char) * (wsize + 1));

while(1) <
word[ll] = (char)fgetc(f);
if(ll==wsize) <
word[ll+1] = ‘\0’;
wsize+=102400;
word = (char *)realloc(word,sizeof(char)*(wsize+1));
>
—(*cl);
if((word[ll] == stop) || (feof(f)) || (!(*cl))) <
if(word[ll] != stop) ll++;
word[ll] = ‘\0’;
return word;
>
++ll;
>
>

char x2c (char *what) <
/* Предназначена для преобразования шестнадцатиричного кода символа в код символа
*/
register char digit;

digit = (what[0] >= ‘A’ ? ((what[0] & 0xdf) — ‘A’)+10 : (what[0] — ‘0’));
digit *= 16;
digit += (what[1] >= ‘A’ ? ((what[1] & 0xdf) — ‘A’)+10 : (what[1] — ‘0’));
return(digit);
>

void unescape_url (char *url) < register int x,y; for(x=0,y=0;url[y];++x,++y) <
if((url[x] = url[y]) == ‘%’) <
url[x] = x2c(&url[y+1]);
y+=2;
>
>
url[x] = ‘\0’;
>

void plustospace (char *str) <
/*замена символов «+» на символ «пробел»*/
register int x;

for(x=0;str[x];x++) if(str[x] == ‘+’) str[x] = ‘ ‘;
>

Для демонстрации реализации формы с методом запроса GET воспользуемся той же самой формой, что и для метода POST и программой query. Для этого изменим значение атрибутов ACTION и METHOD в теге FORM.

использование: предназначен для получения информации от клиента и определяет начало и конец формы.

атрибуты:

    Обязательные
    ACTION — определяет URI (Universal Resource Identifier-адрес или место расположения документа) CGI-скрипта
    METHOD — определяет метод передачи информации скрипту. Возможные значения GET или POST.
  • Необязательные
    [ENCTYPE] — определяет тип MIME декодирования информации (значение этого атрибута по умолчанию — «application/x-www-form-urlencoded»).
    [SCRIPT] — используется для передачи URI скрипта. Язык скрипта и интерфейс пользователя при этом не являются частью спецификации HTML 3.0
  • Важно: Формы не могут быть вложенными!

    Для реализации формы используются следующие теги.

    использование: предназначен для создания различных по своей функциональности полей ввода.

    TYPE — определяет тип поля формы.

      Допустимые значения:
      TEXT — позволяет символьный ввод.
      PASSWORD — предназначено для «скрытого» ввода символов (вводимые символы не отображаются).
      CHECKBOX — поле, позволяющее два состояния («есть», «нет»). Должен применяться с атрибутами NAME и VALUE
      RADIO — поле, позволяющее выбор «один из всех»
      SUBMIT — кнопка инициирующая передачу информации из формы обрабатывающему скрипту, определенному в ACTION в соответствии с методом, определенным атрибутом METHOD.
      RESET — кнопка, сбрасывающая все введенные ранее значения.
      IMAGE — поле позволяющее воспроизвести событие SUBMIT при помощи вашего изображения, при этом возвращается два значения: name.x = координата Х и name.y = координата Y, где Х и Y координаты положения курсора мыши на изображении в момент щелчка.
      HIDDEN — поле создающее неотображаемое значение.
      RANGE — определяет поле позволяющее ввести цифровое значение с определенными допустимыми верхним и нижним пределами.
      Используется вместе с атрибутами MAX и MIN определяющими область допустимых значений (например: TYPE=RANGE MIN=1 MAX=10).

    NAME — значение этого атрибута определяет идентификатор поля.
    VALUE — значение этого атрибута определяет что будет передано в качестве значения по умолчанию для данного поля при инициации формы.
    SRC — определяет URI файла изображения. Используется только с типом поля IMAGE.
    [CHECKED] — позволяет установить начальное значение поля типа CHECKBOX.
    SIZE — определяет размер поля.
    [MAXLENGTH] — определяет максимальное количество символов, допустимое для ввода в поле.
    [ALIGN] — позволяет позиционирование

      Допустимые значения:
    • по вертикали
      TOP — выравнивание по верху.
      MIDDLE — выравнивание по середине.
      BOTTOM выравнивание по низу.
      Эти значения используются только с TYPE=IMAGE.
    • по горизонтали
      [LEFT] — выравнивание слева
      [RIGHT] — выравнивание справа

    [DISABLED] — определяет поле как «read only» — только для чтения. Значение в поле не может быть изменено пользователем.
    [ERROR] — определяет сообщение об ошибке, объясняющее, почему введенное значение в поле не верно.

    использование: предназначен для определения области ввода текста. Размер поля определяется атрибутами.

    NAME — значение этого атрибута определяет идентификатор поля. Возвращается при инициации формы.
    ROWS — определяет количество строк в текстовой области.
    COLS — определяет количество столбцов в текстовой области.
    [VALUE] — задает значение по умолчанию.
    [DISABLED] — определяет поле как «read only» — только для чтения. Значение в поле не может быть изменено пользователем.
    [ERROR] — определяет сообщение об ошибке, объясняющее, почему введенное значение в поле не верно.

    использование: предназначен для определения области выбора из нескольких значений (меню).

    NAME — значение этого атрибута определяет идентификатор поля. Возвращается при инициации формы.
    [SIZE] — определяет количество видимых возможных значений.
    [MULTIPLE] — определяет возможность множественного выбора.
    [DISABLED] — определяет меню как «read only» — только для чтения. Значения в меню не может быть выбрано пользователем и показывается серым цветом.

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

    SELECTED — определяет значение по умолчанию
    VALUE — определяет возвращаемое значение

    Примечание: в [ ] даны необязательные атрибуты

    Разработка cgi

    CGI.pm — Original author(s) Lincoln Stein Stable release 3.49 / 2010 02 05 Platform Perl Type Perl module for CGI … Wikipedia

    CGI — 〈EDV; Abk. für engl.〉 Common Gateway Interface (allgemeine Schnittstelle) * * * CGI [Abk. für Common Gateway Interface, dt »allgemeine Schnittstelle für den Übergang (zwischen einem Webserver und Programmen)«], ein Standard im World W >Universal-Lexikon

    CGI — may refer to: Contents 1 Technology 2 Organizations 3 Other 4 See also Technology Computer generated imagery … Wikipedia

    CGI — Saltar a navegación, búsqueda La sigla CGI puede referirse: Common Gateway Interface, una tecnología que se usa en los serv >Wikipedia Español

    CGI — 〈EDV; Abk. für engl.〉 Common Gateway Interface (allgemeine Schnittstelle) … Lexikalische Deutsches Wörterbuch

    cgi — by 2004, acronym for computer generated imagery … Etymology dictionary

    CGI — (Common Gateway Interface) interface used to access information banks through http services on the Internet (Computers) … English contemporary dictionary

    CGI — DEFINICIJA krat. int. 1. standardno sučelje između klijenta i poslužitelja 2. specifikacija koja određuje format i sintaksu za prosljeđivanje podataka web poslužiteljima od strane klijenta ETIMOLOGIJA engl. Common Graphics Interface (Common… … Hrvatski jezični portal

    CGI — in full Common Gateway Interface. Specification by which a Web server passes data between itself and an application program. Typically, a Web user will make a request of the Web server, which in turn passes the request to a CGI application… … Universalium


    CGI — abbrev 1. City and Guilds (of London) Institute (also CGLI) 2. Computer generated imagery. * * * CGI UK [ˌsiː dʒiː ˈaɪ] US [ˌsi dʒi ˈaɪ] noun computing computer generated imagery: images produced by a computer Thesaurus: abbreviations used in… … Useful english dictionary

    CGI-скрипты: что это, способы создания

    CGI — это аббревиатура от слов Common Gateway Interface. Так называется небольшая программа, которая предлагает надежный способ взаимодействия веб-серверов в браузере, выполняя это способами, которые были невозможны с помощью HTML. Большинство скриптов CGI написаны на Perl. Это обычный язык программирования, который используется для создания сценариев на стороне сервера со стандартным текстовым файлом с расширением (.cgi).

    Основные условия работы программы

    Прежде чем использовать символы CGI скриптов, пользователь должен проверить, поддерживает ли их веб-узел сайта, а также уточнить, если ли у разработчика полномочия на их применение. Некоторые хосты этого не допускают. Если разработчик сайта видит папку CGI-bin при загрузке HTML-файлов, ему разрешено использовать сценарии GCI.

    Одни хосты позволят запросить у них функцию CGI-bin, поскольку она не всегда предоставляется по умолчанию. Другие хосты могут протестировать и одобрить сценарии, прежде чем дать разрешение на использование CGI скриптов.

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

    Кроме того, понадобится программа FTP, которая поставляется с коммерческой версией Pro или бесплатной версией Lite. Любой вариант будет работать до тех пор, пока он загружается в режиме ASCII, чтобы помочь пользователю пройти через установку, так как создание CGI скриптов может занять много времени.

    Конфигурация и монтаж

    Если у пользователя есть CGI-bin, то имеется хороший шанс для выполнения сценария CGI. Для правильной установки предварительно рекомендуется посмотреть страницу часто задаваемых вопросов веб-хоста, панель управления сайтом, документы поддержки или установочное сообщение. Одной из наиболее распространенных ошибок для веб-мастеров является установка скриптов CGI с неправильным путем.

    Если уже есть сценарий, открытый для использования, путь должен быть правильным, иначе сервер не будет работать. Пока открывается скрипт, проверяют обратную связь относительно любых переменных, которые требуют настройки и комментарии этой строки, начинающиеся с «#».

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

    Разрешение для файлов

    Существует три типа доступа к данным с тремя разными разрешениями для каждой группы.

    Серверы UNIX позволят установить разные уровни доступа. Важно знать, какие разрешения имеет сценарий:

    1. Группа — состоит из добавленных пользователей на сервере. При необходимости будет разрешено удалить их разрешение.
    2. Пользователь — состоит только из владельца файла в группе, это учетная запись хостинга.
    3. Другое — группа состоит из всех других аспектов на сервере.
    4. Чтение — позволяет пользователям читать и понимать данные, указанные в файле.
    5. Write — разрешение на запись позволит пользователям расшифровать и записать новую дату, удалить старые данные из архива.
    6. Execute — разрешение на выполнение, позволит отправлять файл только в том случае, если программа или Upload скрипт CGI exe исполняются. Предварительно убеждаются, что скрипт будет работать до ссылки в режиме общего пользования.

    Пример использования Application

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

    Имеет легкий вес (с точки зрения использования памяти), что делает его подходящим для обычных сред CGI, и высокий выбор производительности в таких постоянных средах, как FastCGI или mod_perl.

    Добавляя PLUG-INS по мере роста потребностей, можно использовать сложные функции, когда они будут нужны, например, нужно написать приложение для поиска через базу данных виджетов. Скрипт экземпляра — это то, что фактически вызывается пользовательским веб-сервером. Это очень маленький простой файл, который просто создает экземпляр пользовательского приложения и вызывает унаследованный метод, run (). Ниже приведено полное описание «widgetview.cgi»:

    #!/usr/bin/perl -wuse WidgetView

    my $webapp = WidgetView->new()

    Как можно видеть, widgetview.cgi просто использует прикладной модуль, который реализует пакет Perl под названием WidgetView.pm.

    CGI Application заботится о внедрении методов new () и run (). При этом пользователь никогда не должен вызывать print () для отправки любого вывода в STDOUT. Вместо этого весь вывод возвращается, как скаляр.

    CGI — самый значительный вклад в управление состоянием приложения. Все, что необходимо для продвижения приложения вперед, это установить значение параметра формы HTML «rm» в значение «режима выполнения», которое нужно обработать отправкой формы. Это ключ к CGI Application.

    Методы сценариев

    Используя CGI Application, пользователь получает доступ к целому ряду встроенных методов. Ниже перечислены те, которые, вызываются из скрипта.

    Метод new () является конструктором для CGI. Он возвращает ссылку на пакет приложений (класс). Он может принимать набор параметров, как пары: ключ => значение.

    Этот метод может принимать некоторые конкретные параметры:

    1. TMPL_PATH — определяет путь к каталогу шаблонов.
    2. QUERY — позволяет указать уже созданный объект запроса CGI.pm.
    3. PARAMS — этот параметр, позволяет установить во время выполнения ряд настраиваемых режимов. Передавая различные значения в сценариях разных экземпляров, которые используют один и тот же модуль приложения, можно достичь более высокого уровня повторного использования.

    Run () вызывается на объект Application Module из скрипта. При вызове он выполняет функциональные возможности пользовательского прикладного модуля.

    Этот метод сначала определяет состояние приложения, просматривая значение параметра CGI, заданного параметром mode_param (). По умолчанию В «rm» для В «Run Mode», который будет содержать имя режима работы. Если это не указано, состояние по умолчанию равно значению start_mode (). Как только режим определен, run () просматривает таблицу отправки, хранящуюся в run_modes (), и находит указатель функции, который вводится из имени режима. Если найден, функция вызывается, а возвращаемые данные print () ‘ed отправляются в STDOUT и в браузер. Если указанный режим не найден, в таблице run_modes (), run () будет croak ().

    Поддержка PSGI

    Приложение предлагает встроенную поддержку PSGI. Объектом запроса по умолчанию для этого является:

    Самый простой способ — создать и вернуть PSGI — совместимый coderef. Нужно передать аргументы в hashref так же, как и к новому. Это возвращает PSGI-совместимый coderef, используя CGI . PSGI в качестве объекта запроса. Чтобы использовать другой объект запроса, создают собственный объект run_as_psgi(), как показано ниже:

    my $psgi_aref = $webapp->run_as_psgi

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

    Спецификация PSGI позволяет возвращать дескриптор файла или ссылку подпрограммы вместо байтовых строк. В режиме PSGI это поддерживается непосредственно CGI Application.

    Методы возможного переопределения

    CGI реализует некоторые методы, которые, как ожидается, будут переопределены путем их реализации в модуле подкласса. Эти методы заключаются в следующем:

    1. Настройка(). Этот метод вызывается унаследованным методом конструктора new ().
    2. Метод setup () следует использовать для определения следующего свойства / методов.

    Метод setup () может вызывать любой из методов экземпляра пользовательского приложения. Эта функция является хорошим местом для определения свойств, специфичных для приложения, с помощью $ webapp-> param ().

    Метод setup () может быть реализован, как изображение ниже:

    Однако часто все, что должно быть в setup (), определяет режимы запуска AutoRunmode, что позволяет сделать это с помощью простого синтаксиса, используя атрибуты режима запуска.

    Метод teardown (). Если он реализован, то вызывается автоматически после создания CGI скриптов и запуска приложения. Его можно использовать для очистки после операций. Типичное использование функции teardown () — отключить соединение с базой данных, которое было установлено в функции setup (). Также можно использовать метод teardown () для хранения информации о состоянии приложения на сервере: cgiapp_init ().

    Отправка чистых URI для запуска режимов

    Современные веб-фреймворки обходятся без ограничений в URI, обеспечивая вместо этого чистые URI:

    Чистым URI для описания одного и того же ресурса может быть:

    Процесс сопоставления этих URI для запуска режимов называется диспетчеризацией и обрабатывается CGI :: Application :: Dispatch. Дополнительный диспетчер не требуется.

    Можно работать над проектом CGI :: Application на рабочем столе или ноутбуке без установки полнофункционального веб-сервера, такого как Apache. Вместо этого устанавливают CGI :: Application :: Server из CPAN. После нескольких минут установки у пользователя будет собственный сервер приложений.

    Проводят автоматизированное тестирование. Test :: WWW :: Mechanize :: CGIApp позволяет выполнять функциональное тестирование проекта CGI :: App без запуска веб-сервера. Test :: WWW :: Mechanize можно использовать для проверки приложения через настоящий веб-сервер.

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

    Пользовательский контент CGI

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

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

    1. Полная информация о запросе, включая имя/IP удаленного хоста, запрошенный URL и его аргументы, строку запроса (если они есть).
    2. Куки, связанные с запросом.
    3. В случае запроса POST, в результате отправки веб-формы, имена и значения параметров.

    Основной пример скрипта PHP

    Сценарий должен выполнить процесс, а затем выводить допустимый HTML-код, включая заголовки HTTP. Пример скрипта PHP:

    В этом скрипте первая и последняя строки являются HTML-кодом, а предложения PHP заключены в маркеры, затем получают скрипт из браузера, добавляя строку запроса из двух аргументов «data1» и «data2».

    Помимо глобальной переменной $ _SERVER в скрипте доступны следующие ассоциативные массивы запуска CGI скриптов:

    1. $ _GET — имена и значения аргументов, переданных серверу в запросе GET.
    2. $ _POST — имена и значения параметров, отправленных на сервер в запросе POST, при отправке формы.
    3. $ _COOKIE — имена и значения файлов cookie, прикрепленных к запросу.
    4. $ _REQUEST — все элементы в $ _GET, $ _POST и $ _COOKIEnpm для запуска php-скриптов с nodejs через cgi. Этот модуль был разработан для deskshell, чтобы обеспечить беспрепятственную обработку сценариев php.

    Учитывая, что разработчик получает запрос в nodejs и имеет объект запроса, называемый req, и объект ответа, называемый res, он должен использовать этот модуль, как представлено ниже:

    Таким образом запрос на /test.php будет отвечать модулю php для скриптов CGI. Функция paramsForRequest считывает объект запроса и устанавливает правильные переменные среды cgi для запроса. Это предоставляется, как отдельная функция, поэтому при необходимости можно добавлять дополнительные переменные запроса. Функция detectBinary в окнах ищет дополнительный модуль узла «php-bin-win32», который предоставляет переносимый php-файл. Этот код работает для deskshell и в том случае, если необходимо использовать его для каких-либо других целей и дополнительных функциях.

    Первая программа

    Чтобы написать простую программу CGI в Perl, придерживаясь традиции, используют фразу «привет мир». Здесь она представлена полностью. Сохраняют это в файл с именем «hello» в каталоге cgi-bin и запускают его, указав URL-адрес:localhost/cgi-bin/hello в браузере. Пользователь должен увидеть текст «Hello world» в браузере. Если нет, знакомятся с разделом boxout для отладки программ CGI, чтобы получить помощь в отслеживании проблемы.

    Это простая программа. Есть только несколько моментов, которые отличают разработку CGI скриптов на Perl от стандартной программы, запускающейся из командной строки. Первой из них является опция -T на линии shebang. Это переводит Perl в режим «taint». В этом режиме Perl автоматически будет игнорировать любые данные, поступающие от пользователя, и не позволит передавать эти данные в операционную систему до тех пор, пока они не будут очищены. В этом смысле taint-режим — хорошая идея.

    Второе отличие заключается в добавлении строки, которая печатает заголовок содержимого. Это будет первая проба пользователя с протоколом CGI.

    Все программы CGI должны выводить набор заголовков в браузер пользователя. В большинстве случаев единственным заголовком, который нужно будет вернуть, является контент. Это сообщает браузеру, какие данные программа отправляет. В этом примере возвращается простой текст, поэтому тип содержимого был «text/plain».

    Обычно возвращают HTML, поэтому тип контента будет «text / html». Нет причин, по которым программа не может вернуть более сложные данные, например PNG («image / png»). Набор заголовков должен быть отделен от фактических данных пустой строкой. Это достигается путем печати двух символов новой строки после финального заголовка CGI скриптов на сервере.Также обращают внимание, что программа записывает свой вывод в STDOUT.

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

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

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

    Если пользователь когда-либо просматривал настройки своего браузера, вероятно, видел флажки или переключатели для включения или отключения Javascript и Java, но никогда не видел их для CGI или PHP. Это потому, что Javascript и Java выполняются браузером (или нет, если пользователь отключит их). Браузер ничего не знает о CGI или PHP. Он просто получает чистый HTML-код после выполнения сценариев на сервере. Встроенный способ создания CGI скриптов — PHP, ColdFusion, ASP, в основном, используется разработчиками, создающим веб-страницы «front end», которые будут обращаться к базам данных «назад», например, клиент/серверные веб-приложения.

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

    Илон Маск рекомендует:  Что такое код mcrypt_get_block_size
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL