СТАТЬЯ
10.08.01

Создание Web-приложений с помощью C++Builder 5

Наталия Елманова
КомпьютерПресс #2 2001

Статья была опубликована в КомпьютерПресс (www.cpress.ru)

Данная статья посвящена одной из неплохо зарекомендовавших себя технологий создания динамических интерактивных Web-сайтов — разработке CGI- и ISAPI-приложений. Будучи далеко не единственной технологией создания таких Web-сайтов, она тем не менее остается довольно популярной. В данной статье мы рассмотрим примеры создания CGI- и ISAPI-приложений, выполняемых под управлением Microsoft Internet Information Services, с помощью C++Builder 5. О других способах создания динамических Web-сайтов, например разработке ASP-приложений, вы можете прочитать в статье Сергея Трепалина «Создание серверных компонентов для ASP-приложений» на этом же CD-ROM.

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

Применение Интернета в широком смысле означает доступ к ресурсам, содержащимся в Сети. Любой ресурс Интернета однозначно идентифицируется с помощью адреса URL (Uniform Resource Locators), который можно ввести в соответствующем поле браузера либо выбрать, щелкнув мышью на гипертекстовой ссылке Web-страницы или другого документа. Примерами Интернет-ресурсов являются HTML-страницы, документы различных форматов, Java-аплеты, элементы управления ActiveX и другие файлы. Результат выполнения какого-либо приложения, управляемого Web-сервером, также является ресурсом Интернета, и если настройки уровня безопасности браузера позволяют использовать этот ресурс, он также будет интерпретирован браузером. Отметим, что приложения, выполняемые под управлением Web-серверов и являющиеся источником подобных ресурсов, способны обрабатывать параметры, содержащиеся в запросе пользователя, и результат их работы может зависеть от этих параметров.

Создать Web-приложение, динамически генерирующее подобные ресурсы (обычно HTML-документы), можно с помощью практически любого средства разработки — лишь бы оно позволяло создавать приложения для той операционной системы, в которой работает Web-сервер. Однако если вы хотите снизить трудозатраты, связанные с созданием таких приложений, то имеет смысл обратить внимание на средства разработки, позволяющие их минимизировать. С этой точки зрения довольно удачным выбором являются Borland Delphi 5 и Borland C++Builder 5 (редакции Enterprise и Professional), а также Delphi 4 и C++Builder 4 Enterprise, так как эти средства разработки содержат неплохие визуальные инструменты и компоненты для создания подобных приложений.

Рассматриваемые в настоящей статье примеры или их аналоги, если это особо не оговорено, можно создавать с помощью любого из перечисленных выше средств разработки. Сами примеры созданы с помощью C++Builder 5 Enterprise, но, думаю, пользователям Delphi не составит особого труда перенести их код на Object Pascal.

Изучение разработки Web-приложений мы начнем с создания простейшего примера.

Возврат Простейшее Web-приложение

Для создания простейшего Web-приложения из главного меню среды разработки C++Builder выберем пункт File | New и в репозитарии объектов выберем пиктограмму Web Server Application (рис. 1).

Далее нужно выбрать тип приложения (исполняемый файл CGI или Win-CGI либо динамически загружаемая библиотека ISAPI/NSAPI DLL, представляющая собой функциональное расширение для Microsoft Internet Information Services или Netscape FastTrack). CGI-скрипт (CGI-Common Gateway Interface), будучи исполняемым файлом, запускается в отдельном процессе, в то время как ISAPI/NSAPI DLL (динамически загружаемая библиотека — выполняется в адресном пространстве Web-сервера. Поэтому ISAPI/NSAPI DLL требуют меньше ресурсов, чем CGI-скрипты. К тому же такие библиотеки после загрузки остаются в памяти сервера, что уменьшает время их отклика на последующие обращения к ним. Однако это мешает их отладке: после внесения в библиотеку каких-либо изменений необходим перезапуск Web-сервера. В связи с этим при разработке Web-приложений нередко сначала создается CGI-скрипт, который затем отлаживается, после чего на основе имеющихся модулей создается ISAPI/NSAPI DLL. Так мы и поступим: выберем опцию CGI Stand-alone executable и создадим Win32-консольное приложение для генерации HTML-документов. В результате получим объект TWebModule, напоминающий обычный модуль данных(рис. 2).

Рассмотрим, как работает Web-приложение. Если Web-сервер получает от браузера запрос, соответствующий спецификации CGI, он инициирует запуск CGI-приложения для его выполнения. Если запрос корректен, CGI-приложение обрабатывает его и генерирует HTML-документ, который отсылается Web-сервером обратно в браузер. Для обмена данными между браузером и сервером используется протокол HTTP (HyperText Transfer Protocol).

Когда Web-приложение получает HTTP-запрос, оно создает объект TWebRequest для представления запроса и объект TWebResponce для представления отклика, отправляемого в браузер пользователя. Затем оба объекта передаются объекту TWebModule (рис. 3).

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

Для того чтобы приложение было работоспособным, создадим хотя бы один объект TWebActionItem, реализующий отклик на пользовательский запрос. С этой целью из контекстного меню объекта TWebModule надо выбрать пункт Action Editor и нажать кнопку Add в появившейся форме. Далее можно установить свойства PathInfo и Default объекта WebActionItem1. Первое свойство является частью URL (Uniform Resource Locator) — полного описания доступа к ресурсу (рис. 4).

Свойство Default указывает, выполняется ли данный отклик, если параметр PathInfo в пользовательском запросе остался пустым (рис. 5).

Теперь создадим обработчик события OnAction компонента TWebActionItem:

void __fastcall TWebModule1::WebModule1WebActionItem1Action(
   TObject *Sender, TWebRequest *Request, TWebResponse *Response,
   bool &Handled)
{
   AnsiString cont = AnsiString("<HTML><BODY><H3>Hello!</H3>");
   cont = cont + AnsiString("<BR>");
   cont = cont + AnsiString("<H2>Now is   ") + TimeToStr(Time()) +
             AnsiString("   </H2>");
   cont = cont + AnsiString("</BODY></HTML>");
   Response->Content = cont;
}

В этом обработчике события генерируется содержащая текущее время HTML-страница примерно следующего вида (рис. 6):

Сделаем одно небольшое, но важное замечание. Перед компиляцией такого приложения в С++Builder в опциях проекта следует отключить опцию Use dynamic RTL на странице Linker. Кроме того, стоит отключить и опцию Build with runtime packages на странице Packages либо поместить все эти библиотеки в тот же каталог, что и само приложение (рис. 7).

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

CGI Error
The specified CGI application misbehaved by not returning a complete set of HTTP headers. The headers it did return are: ...

Отметим, что при создании ISAPI DLL с использованием Delphi 4 или C++Builder 4 в такой библиотеке не должно быть «пакетов» — она обязательно должна состоять из одного файла.

После компиляции приложения можно сохранить полученный исполняемый файл в каталоге, предназначенном для Web-приложений (в случае MS Internet Information Services по умолчанию это каталог C:\Inetpub\scripts). Затем можно обратиться к приложению через Web-браузер, указав URL-приложения. Обратите внимание: внешнему пользователю, обращающемуся к созданному приложению через браузер, не видна (и не должна быть видна) структура каталогов компьютера, содержащего Web-сервер, — вместо этого ему следует вводить их псевдонимы. Такой подход к использованию каталогов Web-сервера необходим для обеспечения безопасности — внешний пользователь ничего не должен знать о файлах и каталогах компьютера, содержащего Web-сервер, кроме того что ему положено.

Запустив приложение, можно нажать кнопку Reload и убедиться, что текст в браузере меняется. Это значит, что страница генерируется динамически (рис. 8).

Из этого CGI-скрипта мы можем создать ISAPI DLL. Для этого следует создать новое Web-приложение в виде ISAPI DLL, удалить из него объект TWebModule, а вместо него добавить другой объект TWebModule из предыдущего проекта.

Возврат Создание форм и обработка пользовательского ввода

Отметим, что объект TWebModule существенно облегчает создание CGI-приложений, связанных с обработкой пользовательского ввода (например, в HTML-формах), заключающегося в изменении или добавлении данных. Типичными примерами таких приложений являются анкеты, которые в изобилии встречаются на многих Web-серверах. Дополним наше приложение такой анкетой.

Для отображения в браузере формы ввода данных пользователем создадим еще один компонент TWebActionItem (рис. 9):

Установим свойство Default вновь созданного объекта TWebAction равным True. Теперь добавим в WebModule1 компонент TPageProducer, назначение которого — генерировать HTML-документ на основе заранее заданного шаблона (рис. 10).

Для создания шаблона документа можно воспользоваться любым HTML-редактором, поддерживающим создание форм, например Microsoft FrontPage (рис. 11).

Исходный текст формы, представленной на рис. 11, имеет вид:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
   charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title>Untitled Normal Page</title></head>
<body bgcolor="#FFFFFF">
<p>&nbsp;</p>
<form method="GET">
<p>What is Your name?<font size="4">
<input type="text" size="20" name="T1"></font></p>
<p>What is Your e-mail?<font size="4">
<input type="text" size="20" name="T2"></font></p>
<p><font size="4"><input type="submit" name="B1"
   value="Submit"><input type="reset" name="B2"
   value="Reset"></font></p>
</form>
</body>
</html>

Созданный документ можно сохранить в виде файла (и указать его имя в качестве свойства HTMLFile компонента TPageProducer). Можно также скопировать HTML-текст в буфер обмена и поместить его в редактор свойства HTMLDoc этого компонента.

Теперь создадим обработчик события OnAction сгенерированного нами компонента TWebActionItem2:

void __fastcall TWebModule1::WebModule1WebActionItem2Action(
   TObject *Sender, TWebRequest *Request, TWebResponse *Response,
   bool &Handled)
{
   Response->Content=PageProducer1->Content();
}

Отметим, что в Delphi 5 и C++Builder 5 компонент TWebAction имеет свойство Producer, позволяющее непосредственно указать, какую именно HTML-страницу нужно генерировать при обращении. Это во многих случаях избавляет от необходимости создавать обработчик события OnAction данного компонента.

Сохранив проект, можно снова обратиться к нему с помощью браузера, указав значение PathInfo в URL (рис. 12):

Теперь осталось обработать пользовательский ввод, например, динамически сгенерировав страницу с введенными пользователем значениями. С этой целью добавим еще один компонент — TPageProducer (рис. 13): страницы, содержащей результаты обработки пользовательского ввода

В качестве значения свойства HTMLDoc вновь созданного компонента PageProducer2 введем следующий текст:

<html>
<head>
<title>Thank You!</title>
</head>
<body >
<p>Dear   <#T1>!</p>
<p>Thank you for completing this form. We have included your
e-mail address <#T2> in our mailing list. You will receive a
lot of spam from us!</p>
</body>
</html>

Данный текст представляет собой шаблон документа. Он содержит специальные тэги, заменяемые в процессе формирования HTML-страницы строками, которые, в свою очередь, могут быть введены пользователем в созданную выше форму. В нашем случае это тэги <#T1> и <#T2>. Они представляют собой имена полей ввода в созданной ранее форме, в чем можно убедиться, просмотрев HTML-текст формы.

Для замены специальных тэгов следует создать обработчик события OnHTMLTag компонента PageProducer2:

void __fastcall TWebModule1::PageProducer2HTMLTag(
   TObject *Sender, TTag Tag, const AnsiString TagString,
   TStrings *TagParams,   AnsiString &ReplaceText)
{
   ReplaceText = Request->QueryFields->Values[TagString] +
      Request->ContentFields->Values[TagString];
}

Здесь Request — объект TWebRequest, сгенерированный приложением в результате пользовательского запроса. В свойстве QueryFields (объект TStrings) этого объекта содержатся имена параметров и значения, введенные пользователем, в виде Name=Value (реально они содержатся в переменной окружения QUERY_STRING, созданной Web-сервером, в виде Name1=Value1&Name2=Value2&…). Параметр TagString — строка, содержащаяся в тэге, подлежащем замене. Cвойство Values объекта TStrings используется, если строки, содержащиеся в этом объекте, представимы в виде Name=Value (что и происходит в данном случае).

Отметим, что если в тэге <form>, содержащемся в тексте формы, вместо метода GET указан метод POST, то вместо свойства QueryFields следует использовать свойство ContentField.

Теперь создадим еще один компонент TWebAction (со значением свойства PathInfo, равным /test3) для отображения страницы, сгенерированной с помощью PageProducer2, и добавим еще один обработчик события OnAction:

void __fastcall TWebModule1::WebModule1WebActionItem3Action(
   TObject *Sender, TWebRequest *Request, TWebResponse *Response,
   bool &Handled)
{
   Response->Content=PageProducer2->Content();
}

Возникает вопрос: каким образом можно инициировать генерацию этой страницы после нажатия пользователем кнопки Submit в форме ввода? С этой целью следует описать реакцию на ее нажатие в HTML-тексте формы, то есть отредактировать свойство HTMLDoc компонента PageProducer1:

<form method="POST" 
   action="http://mywebserver/scripts/formproc.exe/t3">

В параметре action указывается URL ресурса, предоставляемого при нажатии кнопки Submit. В данном случае это наше приложение со значением PathInfo, равным /test3 (естественно, имя Web-сервера, так же как и другие части URL, может быть другим).

Теперь можно снова скомпилировать и сохранить приложение. Обратившись к нему с помощью браузера и заполнив форму, нажмем на кнопку Submit. В результате получим страницу, сгенерированную динамически на основе введенных в форму данных (рис. 14):

Из этого CGI-скрипта, как и в предыдущем случае, можно создать ISAPI DLL.

Продолжение статьи

Дополнительную информацию Вы можете получить в компании Interface Ltd.

Отправить ссылку на страницу по e-mail
Обсудить на форуме Inprise/Borland


Interface Ltd.
Тel/Fax: +7(095) 105-0049 (многоканальный)
Отправить E-Mail
http://www.interface.ru
Ваши замечания и предложения отправляйте автору
По техническим вопросам обращайтесь к вебмастеру
Документ опубликован: 10.08.01