Chapter 2 - A First Module
Apache Web Server
Вам нужна рабочая версия самого апача , желательно последняя
(для подготовки этой книги была использована версия 1.3.4).
Его можно загрузить отсюда : http://www.apache.org/.
Пользователи NT могут загрузить откомпилированные бинарники.
Для этого вам нужно 2 компонента:
сам сервер на http://www.apache.org/dist/,и ApacheModulePerl.dll.
Последний можно найти на Comprehensive Perl Archive Network (CPAN)
в каталоге authors/Jeffrey_Baker/.
Этот модуль можно откомпилировать с помощью Microsoft Visual C++ .
C-компилятор и утилита make
Для использования C API вам нужен C-компилятор и утилиты.
GNU gcc компилятор доступен например с веб-сайта http://www.gnu.org/.
Perl
Для использования Perl API вам нужен Perl не ниже 5.004 .
Его можно найти например на CPAN .
Последние версии CGI.pm и LWP
CGI.pm - коллекция прикладных утилит .
Рекомендованная версия - не ниже 2.42 .
LWP (Library for WWW access in Perl) - коллекция модулей для создания веб-роботов ,
агентов , броузеров на перл .
LWP необходим для создания прокси . mod_perl использует LWP во время инсталляции.
Рекомендуемая версия LWP - не ниже 5.36 .
CGI.pm и LWP можно найти на CPAN, в каталоге modules/by-module/CGI
и modules/by-module/LWP .
Структура директорий
Server root directory
В нее входят , как правило , /bin-каталог с самим httpd и apachectl-утилитой;
конфигурация и логи лежат в /conf и /logs;
каталог для CGI-скриптов - /cgi-bin;
каталог для динамически загружаемых модулей - /libexec;
хидеры для C - /include;
доки - /htdocs.
Собственно сам default server root каталог , как правило , лежит в /usr/local/apache .
В дальнейшем этот каталог мы будем условно называть ~www.
На Win32-системах этот каталог обычно C:\Program Files\Apache Group\Apache.
Document root directory
Это каталог по умолчанию , который получается , если вызвать http://your.site/.
Apache и mod_perl build
Это каталог , в котором вы компилите сам апач и mod_perl из исходников .
Здесь не бывает стандартов и кто во что горазд : /usr/src, /usr/build, /usr/tmp.
Все же рекомендуется ~www/build .
httpd.conf, srm.conf, access.conf
Это 3 важнейших апачевских конфига .
Их разделение обусловлено исторически для поддержки NCSA httpd.
Некоторые сайты насильственно обьединяют все в один конфиг httpd.conf .
Кстати , такая же настройка по умолчанию и в 1.3.4 Apache.
Другие сайты для каждого хоста имеют свой отдельный конфиг , который загружается
с помощью директивы Include .
В книге используется следующий метод : все основные директивы хранятся в httpd.conf,
включая виртуальные хосты . Apache Perl API директивы помещаются в отдельный файл
perl.conf , который загружается при старт-апе так:
<IfModule mod_perl.c>
Include conf/perl.conf
</IfModule>
Директива <IfModule> позволяет нам использовать единый httpd.conf
для добавления перлового embedded-интерпретатора .
.htaccess
Этот файл можно использовать для изменения конфигурации , не затрагивая основной конфиг .
Он может носить другое название .
cgi-bin
Скриптовый каталог обычно лежит в ~www/cgi-bin.
perl
Каталог перловых скриптов , выполняемых под mod_perl Apache::Registry модулем .
По умолчанию это ~www/perl
Module library tree
Необходимо выделить специальное место под модули , написанные как на перл , так и
на С (файлы с расширением .o и .so ). Обычно это ~www/ libexec .
Чисто перловые модули хранятся в ~www/lib/perl .
"Perl module" и "Apache Perl module"
Когда мы говорим - "module" , мы обычно подразумеваем модуль , написанный на Perl API.
Perl при работе использует при работе целую библиотеку модулей (.pm) .
Нужно различать "Perl module" , которые веб-серверу не нужны , и "Apache Perl module" ,
которые написаны на Apache Perl API и вызываются сервером .
Apache Perl modules обычно начинаются с префикса "Apache::".
Пример:
| Тип модуля | Пример |
---|
| Apache module | mod_mime , mod_rewrite | | Apache Perl module | Apache::AuthenDBI , Apache::Traffic | | Perl module | Text::ParseWords , IO::File |
Perl library tree
Включает Perl-модули, Plain Old Documentation (POD), loadable library objects,
и хидеры для компиляции перловых модулей . Расположение этих каталогов
может быть неожиданным ,
но в основном это /usr/lib/perl5, /usr/local/lib/perl5.
Installing mod_perl
Прежде чем использовать Perl API, нужно загрузить и поинсталлировать mod_perl .
Его можно взять на www.apache.org .
На моем АСП 9.2 конфигурация у апача 2.0 следующая :
основной исполняющий файл лежит в /usr/sbin/httpd
утилиты лежат в /usr/bin
библиотеки .so лежат в /usr/lib/httpd/modules
документация лежит в /usr/share/doc , /usr/share/man
конфиги лежат в /etc/httpd , /etc/logrotate.d
логи лежат в подкаталогах каталога /var
мануал лежит в /var/www/manual
главный start-up-конфиг лежит в /etc/rc.d/init.d/httpd
После закачки и распаковки архива mod_perl-2.0.0-RC3tar.gz я выполнил следующее :
perl Makefile.PL # run installation script
make # make httpd executable
make test # run tests (optional)
make install # install mod_perl
После чего 2.5-метровый mod_perl.so лег на моей машине в каталог
/usr/lib/httpd/modules/mod_perl.so
Необходимо в httpd.conf добавить строку :
LoadModule perl_module modules/mod_perl.so
Для того чтобы получить полный доступ к Apache API , нужно запустить конфигурацию так
perl Makefile.PL EVERYTHING=1 APACHE_PREFIX=/usr/sbin/httpd
Опция EVERYTHING=1 позволяет использовать такие фичи , как поддержка хэндлеров ,
включение SSI на Perl , Perl-секции в конфигах апача .
"Hello World" with the Perl API
Теперь необходимо придумать каталог для модулей , которые мы будем писать .
Я организовал его в /usr/lib/perl5/5.8.1/Apache .
Ложим в этот каталог файл Hello.pm следующего содержания :
package Apache::Hello;
# File: Apache/Hello.pm
use strict;
use Apache::Constants qw(:common);
sub handler {
my $r = shift;
$r->content_type('text/html');
$r->send_http_header;
my $host = $r->get_remote_host;
$r->print(<<END);
<HTML>
<HEAD>
<TITLE>Hello There</TITLE>
</HEAD>
<BODY>
<H1>Hello $host</H1>
Who would take this book seriously if the first example didn't say "hello world"?
</BODY>
</HTML>
END
return OK;
}
1;
В этом модуле всего одна подпрограмма с именем handler().
Добавим в httpd.conf директиву <Location> следующего содержания :
<Location /hello>
SetHandler perl-script
PerlHandler Apache::Hello
</Location>
Перезапустив httpd и набрав URL http://localhost/hello ,
получим соответствующий контент .
"Hello , World" с помощью C API
В этой секции напишем модуль "Hello World" с использованием C API.
Создадим подкаталог с именем site в подкаталоге modules .
Полный путь должен выглядеть аналогично ~www/src/modules/site
Создадим файл с именем Makefile.tmpl. Если модуль состоит из одного файла ,
Makefile.tmpl может быть пустым .
Создадим файл с именем mod_hello.c со следующим содержанием :
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
/* file: mod_hello.c */
/* here's the content handler */
static int hello_handler(request_rec *r) {
const char* hostname;
r->content_type = "text/html";
ap_send_http_header(r);
hostname = ap_get_remote_host(r->connection,r->per_dir_config,REMOTE_NAME);
ap_rputs("<HTML>\n" ,r);
ap_rputs("<HEAD>\n" ,r);
ap_rputs("<TITLE>Hello There</TITLE>\n" ,r);
ap_rputs("</HEAD>\n" ,r);
ap_rputs("<BODY>\n" ,r);
ap_rprintf(r,"<H1>Hello %s</H1>\n" ,hostname);
ap_rputs("Who would take this book seriously if the first example didn't\n",r); ap_rputs("say \"hello world\"?\n" ,r);
ap_rputs("</BODY>\n" ,r);
ap_rputs("</HTML>\n" ,r);
return OK;
}
/* Make the name of the content handler known to Apache */
static handler_rec hello_handlers[] =
{
{"hello-handler", hello_handler},
{NULL}
};
/* Tell Apache what phases of the transaction we handle */
module MODULE_VAR_EXPORT hello_module =
{
STANDARD_MODULE_STUFF,
NULL, /* module initializer */
NULL, /* per-directory config creator */
NULL, /* dir config merger */
NULL, /* server config creator */
NULL, /* server config merger */
NULL, /* command table */
hello_handlers, /* [9] content handlers */
NULL, /* [2] URI-to-filename translation */
NULL, /* [5] check/validate user_id */
NULL, /* [6] check user_id is valid *here* */
NULL, /* [4] check access by host address */
NULL, /* [7] MIME type checker/setter */
NULL, /* [8] fixups */
NULL, /* [10] logger */
NULL, /* [3] header parser */
NULL, /* process initialization */
NULL, /* process exit/cleanup */
NULL /* [1] post read_request handling */
};
Основная работа здесь выполняется в подпрограмме hello_handler() ,
которая получает запрос апача и возвращает целое число .
content_type становится равным text/html, затем вызывается ap_send_http_header().
hello_handler() вычисляет DNS-имя удаленного хоста вызовом ap_get_remote_host() .
Далее строится HTML путем серии вызовов ap_rputs() и ap_rprintf().
Они работают аналогично printf().
В модуле mod_hello интерес представляют 9 фаз транзакции .
Комментарий показывает , в каком порядке они вызываются , хотя вызываются они не все .
Этот модуль необходимо сконфигурировать . Для этого у апача есть специальный конфиг-скрипт .
Аргумет activate-module используется для добавления модуля .
Его аргументом является путь к файлу , в нашем случае это src/modules/site/mod_hello.c.
Аргумент enable-module достаточно активировать 1 раз.
Из головного апачевского каталога , который включает файл ABOUT_APACHE ,
нужно набрать команду :
./configure --activate-module=src/modules/site/mod_hello.c --enable-module=hello
Мы должны увидеть примерно следующий вывод :
Configuring for Apache, Version 1.3.3
+ activated hello module (modules/site/mod_hello.c)
Creating Makefile
Creating Configuration.apaci in src
Creating Makefile in src
+ configured for Linux platform
+ setting C compiler to gcc
+ adding selected modules
+ checking for system header files
+ doing sanity check on compiler and options
Creating Makefile in src/support
Creating Makefile in src/main
Creating Makefile in src/ap
Creating Makefile in src/regex
Creating Makefile in src/os/unix
Creating Makefile in src/modules/standard
После чего запускаем make .
Будет построена статическая библиотека libsite.a.
Добавим в конфиг секцию <Location> :
<Location /hey/there>
SetHandler hello-handler
</Location>
Перезапускаем апач и набираем в броузере URI http://your.site/hey/there
и смотрим на приветствие .
Динамически загружаемые модули
В апаче реализованы динамически загружаемые модули .
Иногда апач нужно перекомпилировать , потому что зачастую такая загрузка
по умолчанию выключена .
Для этого нужно набрать :
./configure --enable-module=so --enable-module=other_module ...
Теперь нужно собрать mod_hello.so. Это можно сделать 2 путями .
Один путь с помощью configure скрипта : все из того же каталога набираем
./configure --activate-module=src/modules/site/mod_hello.c --enable-shared=hello
Теперь запускаем make для создания src/modules/site/mod_hello.so.
Полученный файл .so копируем в каталог libexec:
В httpd.conf добавляем строку с именем модуля и путем :
LoadModule hello_module libexec/mod_hello.so
Второй путь для получения динамического модуля - утилита apxs ,
т.н. "APache eXtenSion"-утилита :
~www/bin/apxs -c -i -a mod_hello.c
Вывод :
gcc -DLINUX=2 -DHAS_BOOL -DUSE_HSREGEX -I/usr/local/apache/include
-c mod_hello.c -o mod_hello.so mod_hello.o
cp mod_hello.so /usr/local/apache/libexec/mod_hello.so
chmod 644 /usr/local/apache/libexec/mod_hello.so
[activating module 'hello' in /usr/local/apache/conf/httpd.conf]
Утилита apxs позволяет хранить модуль где угодно .
Перезапускаем httpd и смотрим в логи , если что-то не так .
Instant-модули и Apache::Registry
При использовании Apache API обычно возникает проблема .
При внесении изменений в Perl API модуль для эффекта нужно перезапускать апач .
При использовании C API надо перестроить библиотеку .
Модуль Apache::Registry является частью mod_perl и призван
решать эту проблему .
Он отслеживает изменения в CGI-скриптах , перекомпилировает их на ходу
без перезапуска апача .
Этот модуль имеет отношение только к Perl CGI-скриптам .
Для инсталляции Apache::Registry нужно создать каталог
для управляемых скриптов .
Рекомендуется ~www/perl. В апачевском конфиге необходимо набрать :
Alias /perl/ /usr/local/apache/perl/
<Location /perl>
SetHandler perl-script
PerlHandler Apache::Registry
PerlSendHeader On
Options +ExecCGI
</Location>
Напишем скрипт hello.pl , положим его в ~www/perl/ , и наберем в броузере
http://your.site/perl/hello.pl.
#!/usr/local/bin/perl
# file: hello.pl
print "Content-Type: text/html\n\n";
print <<END;
<HTML>
<HEAD>
<TITLE>Hello There</TITLE>
</HEAD>
<BODY>
<H1>Hello $ENV{REMOTE_HOST}</H1>
Hello !!!
</BODY>
</HTML>
END
Если сделать изменения в таком скрипте , они вступят в силу немедленно .
Такой скрипт постоянно висит в памяти и загружается быстрее .
С помощью Apache::Registry можно генерировать веб-формы :
#!/usr/local/bin/perl
use CGI qw(:standard);
use strict;
my $name = param('name') || 'Anonymous';
print header(),
start_html(-title=>'Yo!',-bgcolor=>'white'),
h1("Hello $name"),
p(
"To change your name, enter it into the text field below and press",
em("change name.")
),
start_form(),
"Name: ",textfield(-name=>'name',-value=>'Anonymous'),
submit(-value=>'Change Name'),
end_form(),
hr(),
end_html();
|