Узлы Всемирной Паутины - это разбросанные по всему миру миллионы web-серверов. Самым популярным и распространенным в сети Интернет остается web-сервер Apache (www.apache.org), распространяемый свободно с открытыми исходными текстами. Хорошо спроектированная архитектура сервера позволяет подключать к нему модули для расширения функциональности сервера. Одним из популярнейших модулей расширения стал mod_perl, который позволяет интегрировать интерпретатор perl с сервером Apache. Это позволяет не только кардинально увеличить скорость работы CGI-программ, но и разрабатывать на Perl собственные модули, получая полный контроль за выполнением клиентских запросов.
Web-сервер общается с клиентскими программами по протоколу передачи гипертекста HTTP (Hypertext Transfer Protocol). Поскольку весь остальной материал этой лекции связан с передачей данных по указанному протоколу, познакомимся с ним поближе. В соответствии с протоколом HTTP запрос состоит из трех частей, которые приведены в таблице 18.1.
Таблица 18.1. Структура HTTP-запросаСоставные частиОписаниеПримерыСтрока запросасодержит команду, называемую методом, например, GET для запроса ресурса или POST для отправки данных на сервер, и имя ресурсаGET /index.html HTTP/1.1POST /cgi-bin/guestbook.pl HTTP/1.0Заголовки запросасодержат дополнительную информацию, например, данные о клиенте или указания о языке и кодировке ответа, которые предпочитает клиентUser-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.8.0.1) Gecko/20060130 SeaMonkey/1.0Accept-Language: "ru-ru,ru; q=0.8,en-us;q=0.5,en;q=0.3"Тело запросав нем может содержаться передаваемая на сервер информация (например, данные из полей HTML-формы).nick=Ray&[email protected]&comments=Your%20photos%20and%20info%20about%20perl%20are%20fine!
Сервер обрабатывает поступающие от клиентов запросы на расположенные на сервере ресурсы. Если затребован существующий файл, то он отправляется сервером клиенту. Если запрошено обращение к CGI-программе, то сервер запускает ее и отправляет клиенту результат ее выполнения. Ответ HTTP-сервера также состоит из трех частей, которые приведены в таблице 18.2.
Таблица 18.2. Структура HTTP-ответаСоставные частиОписаниеПримерыСтрока ответасодержит цифровой код ответа и текстовое описание состояния запросаHTTP/1.0 200 Document follows HTTP/1.1 404 Not FoundHTTP/1.0 500 Internal Server ErrorЗаголовки ответасодержат дополнительную информацию, например, данные о типе и длине посылаемого ресурсаContent-type: text/htmlContent-length: 1025Тело ответасодержит передаваемые данные<html>...</html>
Важной особенностью протокола HTTP является то, что он ориентирован на обработку независимых запросов, то есть в нем не предусмотрено сохранение состояния взаимодействия с клиентом. Поэтому организация сеансовой работы с web-сервером ложится на программиста.
Автоматизировать рутинные действия при обмене данными с помощью HTTP и преодолеть трудности программного взаимодействия с HTTP-серверами помогают многочисленные готовые Perl-модули. Стандартная библиотека LWP (Library for WWW in Perl) содержит разнообразные и мощные средства для работы с ресурсами WWW. С ее помощью можно легко запрограммировать простые и решить весьма нетривиальные задачи. Например, запрос документа с web-сервера записывается всего одной строкой:
use LWP::Simple; # использовать упрощенный интерфейс к LWP my $page = get 'http://www.perl.com/';
Не сложнее обратиться с запросом к поисковым системам. Для этого нужно в URL указать аргументы поиска. Формат строки запроса к конкретной поисковой машине можно посмотреть в строке браузера. Например, по такому URL можно искать книги по Perl в поисковой системе Google:
$url = 'http://www.google.ru/search?q=Perl+book';
А чтобы найти на сайте CPAN все модули, ориентированные на работу с HTML, нужно отправить такой запрос:
$url= 'http://search.cpan.org/search?query=HTML&mode=module';
Это примеры запросов, отправляемых методом GET, когда аргументы передаются непосредственно в строке, адресующей ресурс. При другом способе запрос отправляется методом POST, а данные запроса отправляются в теле запроса. Если требуется отправить из программы данные HTML-формы на HTTP-сервер методом POST, то это столь же просто делается с помощью LWP:
use LWP::UserAgent; # используем класс 'Клиент' из LWP use HTTP::Request::Common qw(POST); # и метод POST my $user_agent = LWP::UserAgent->new; # создаем клиента # заполняем поля формы для отправки на нужный сайт my $form = POST 'http://site.ru/cgi-bin/guestbook.pl', [ nick => 'user', email => '[email protected]', comments => 'Спасибо за помощь!' ]; # передаем клиенту форму для отправки на сервер my $response = $user_agent->request($form); # получаем ответ print $response->as_string; # и выводим его в виде строки
Можно долго говорить о возможностях библиотеки LWP. С ее помощью можно: работать с новостными группами (news), обмениваться файлами по протоколу FTP, отправлять запросы к информационным системам Gopher, читать локальные файлы, отправлять электронную почту и создавать пользовательских агентов для автоматического исследования сайтов (web-роботов или "пауков"). Можно даже быстро набросать простой, но вполне работоспособный web-сервер. Для этого нужно воспользоваться классом HTTP::Daemon:
use HTTP::Daemon; # используем классы HTTP-сервера my $server_root = '/tmp'; # каталог для файлов сервера # создаем экземпляр WWW-сервера, слушающего порт 8080 my $httpd = new HTTP::Daemon(LocalPort => 8080); # while (my $connection = $httpd->accept) { # ждем соединения # получаем запросы на соединении while (my $request = $connection->get_request) { if ($request->method eq 'GET') { # выполняем GET $connection->send_file_response( # отправляем файл $server_root . $request->url->path); # из каталога } } $connection->close; # закрываем соединение undef($connection); # удаляем объект } # и все повторяется сначала...
А теперь пора перейти к созданию программ, выполняющихся на web-сервере и взаимодействующих с ним через интерфейс CGI.
Упоминавшийся уже интерфейс программирования CGI поддерживается всеми web-серверами. Сегодня CGI-программы разрабатываются не на чистом Perl, а с использованием различных вспомогательных модулей и библиотек. Возможно, самой популярной из них по праву считается стандартная библиотека CGI. С ее помощью можно писать CGI-программы проще, быстрее и надежнее. Разработка программ CGI на Perl описывается во многих специализированных книгах.
В качестве примера напишем простенькую "гостевую книгу" - программу, которая с помощью функций библиотеки CGI (start_html, textfield и т.д.) выводит HTML-страницу с формой для отправки на сайт отзывов посетителей. После отправки данных формы на сервер вызывается эта же CGI-программа, которая с помощью функции param() проверяет, получены ли данные формы, и выводит присланный комментарий. Вот текст программы:
#!C:/usr/local/apache/Perl/bin/perl.exe # в первой строке CGI-программы указан путь к perl use CGI qw/:standard/; # применяем стандартные средства CGI print # выводим в выходной поток header(-charset=>'windows-1251'), # в кодировке CP1251: start_html('Гостевая книга'), # шапку страницы, h3('Здесь Вы можете оставить свой отзыв'),# заголовок, start_form, # форму, в ней "Имя: ", # надпись, textfield(-name=>'nick', size=>8), p, # поле ввода, "Э-почта: ", # надпись, textfield(-name=>'email', size=>32), p, # поле ввода, "Комментарий: ", p, # надпись, textarea(-name=>'comments', # область ввода -rows=>5, -columns=>50), p, # из 5 строк на 50 колонок, submit('Отправить'), # кнопку, end_form, # конец формы hr, "n"; # и горизонтальную черту # далее проверяем, были ли присланы данные формы if (param) { # если присланы данные - параметры формы print # выводим: a({href=>"mailto:".param('email')}, # ссылку на E-mail param('nick')), # и имя, а также " пишет: ", p, param('comments'), p, # комментарий hr,"n"; # и горизонтальную черту } print end_html; # оформляем конец страницы
При первом выполнении эта программа выводит пустую HTML-форму, а после того как форма заполнена и данные формы отправлены на сервер, на странице после формы выводится последний полученный комментарий. В результате будет сгенерирована web-страница, приведенная на рис. 18.1.
Рис. 18.1. Результат выполнения CGI-программы