То, что знают все
Для людей, которые даже никогда сами не имели в своей программерской практике никакого опыта с
Perl само слово
HTML::Mason может быть не ново, а сам
CPAN может вызывать равно как и зависть, так и восторг. Среди огромного количестве библиотечных модулей данного репозитория,
HTML::Mason уже смог выдержать ряд релизов и квалифицироваться не иначе как профессиональная среда разработки веб-ресурсов. Впрочем, можно долго рассуждать на тему того, что именно представляет из себя это явление, но вот с чем приходилось сталкиваться чаще всего, когда произносилось слово “
HTML::Mason”, так это что-то типа: «ну, так без
mod_perl это никак!».
Никто и не скрывает, что данная библиотека и разрабатывалась с этим расширением веб-сервера
Apache в голове; но далеко не все из библиотек, которые присутствуют на
CPAN могут (хотя бы в части pod) «похвастаться» таким разнообразием возможных применений; здесь речь пойдёт о том, как «по одёжке – протягивать ножки», а точнее, как можно используя то, что доступно и под рукой, делать достаточно хорошие и надёжные вещи.
Наверное, найдётся далеко немного людей, которые могут с гордостью сказать, что вот там-то и там-то они использовали
HTML::Mason в полном объёме не только без
mod_perl, но и без
Apache; многое как и это, о чём Вы, наверняка знаете, тоже возможно с данной библиотекой. Однако в данном случае будет немного иная задача, а именно, как используя практически весь арсенал
HTML::Mason заставить его работать на обычном сервере, где есть лишь старый, добрый CGI.pm.
О чём, «молчит» г-н Рольский
Несмотря на то, что в комплекте
HTML::Mason имеется хороший набор документации и масса примеров практически «на все случаи жизни», практика показывает, что то ли умышленно, то ли нет (и этому существует масса свидетельств в интернете, к сожалению) в отношении
CGI имеется там явный пробел. Разумеется, что все, кто когда-либо пытался решить подобную проблему сразу же обращались к
HTML::Mason,
HTML::Mason::Admin,
HTML::Mason::CGIHandler и прочим вещам. И, наверное, большинство из этих смельчаков либо останавливало выбор на чём-то другом, либо... вообщем, это не важно уже сейчас, поскольку это «большинство» приобрёв некоторый печальный опыт «работы» с
HTML::Mason, возможно, уже никогда более не обращало свой взор сюда снова. А жаль! Авторы этих строк никоим образом не ставят всё это в упрёк команде разработчиков
HTML::Mason, но, наверное, всё же стоило пролить свет на возможности
HTML::Mason в этом направлении для массы несведущих.
Итак, что же согласно стандартной документации предлагает данная библиотека всем тем, у кого нет возможности пользоваться всеми прелестями
mod_perl? Сразу надо сказать, что вариантов не очень много и все они, как правило, сводятся к двум.
Вариант использования
HTML::Mason в отдельно взятом (и сделанном) cgi-скрипте с самого начала, даже если не вдаваться в подробности возможной сферы применения, сводит на нет всю мощь
HTML::Mason в части многократного использования в разных местах приложения одних и тех же компонент; а для системных администраторов шаблоны не нужны и вовсе – возможностей Perl хватает с головой. Если кратко, то этот вариант заставляет почти попрощаться с системой шаблонов и, что самое обидное, с тем механизмом, посредством которого они могут взаимодействовать!
Вариант второй указывает на незавершённую эмуляцию взаимодействия
HTML::Mason с
Apache API в виде
HTML::Mason::CGIHandler. По словам самих разработчиков это лишь «жалкое подобие» того, что возможно в связке с
mod_perl. И это действительно так. Вопрос «а надо ли это вообще?» авторами данных строк даже никогда не ставился, а вот стоит ли начинать то, что не очень хочется заканчивать, пока остаётся открытым.
Что по чём и зачем это надо
История открытий и изобретений пестрит примерами, которые родились на стыке двух или более технологий, или просто понятий.
HTML::Mason, в этом смысле, не является исключением, к счастью. Для тех, кто или знаком с историей Интернета, или просто интересовался ею, должна быть известна история возникновения протокола
CGI; который до известного времени удовлетворял всем известным ранее требованиям динамического взаимодействия клиента и сервера. Времена меняются – люди тоже, а вместе с ними и их «игрушки».
Старая сказка про то, что веб-дизайнер никогда не сможет понять веб-разработчика начала, кажется, уже устаревать, когда мир увидел всякого рода системы управления контентом, системы шаблонов и иже с ними. Но всегда и везде первым (хотя, впрочем, и не обязательно первым) встаёт вопрос о платформе. Итак, если побродить по бескрайним просторам Интернета, то краеугольным вопросом, в нашем случае, по-прежнему остаётся наличие
mod_perl у провайдера. Для тех, кто когда-либо занимался подобным «изысканием» должно быть известно, что хостинг подобного рода далеко не копеечный и встречается далеко не везде.
Причин тому достаточно, но главная – в якобы дорогостоящем сопровождении данного вида хостинга, с чем мы не можем согласится (и у нас также есть достаточно причин для этого). Поэтому, возвращаемся к тому что может найтись практически везде – к
CGI.pm со стандартными примочками и что стоит действительно копейки.
HTML::Mason, если не установлен, то получить его на обычном хостинге не есть проблема; все проблемы возникают после того, как окрылённый обладатель готового сайта, который собран согласно документации и вроде бы работает «в домашних» условиях, попытается привинтить его на своем хосте у провайдера.
Чтобы не томить души страждущих, сразу надо сказать, что отправной точкой является наличие
cgi-handler, т.е. скрипта, который «пропускает» через себя все запросы проходящие через CGI окружение и перенаправляет их к
HTML::Mason для дальнейшей работы. До сих пор вроде бы всё ясно; теперь несколько замечаний о святая-святых
HTML::Mason, а именно об
auto- и
dhandler.
В общем и целом, их работа (равно как и содержимое) неизменны, но поскольку то, что в
CGI называется
%ENV, а в
HTML::Mason -
%ARGS (а оно не только называется, но и в самом деле суть две большие разницы) является универсальными контейнерами для обмена данными через переменные окружения (а, как известно mod_perl очень плотно трётся с Apache, а не с
CGI, что и выросло у
HTML::Mason), то неплохо было бы сказать
HTML::Mason откуда их брать, не так ли?
Теория, которая витает в воздухе
В теории, или точнее в документации, говорится, что
autohandler срабатывает прежде всего другого и всегда, а
dhandler только в случае... ну, вообщем, это известно всем. Как оказывается на практике, в
CGI окружении поведение этих рабочих лошадок
HTML::Mason несколько иное. Оказывается, что в таких условиях
dhandler, если всё оставить согласно документации, просто не срабатывает тогда, когда надо; хотя
autohandler работает без проблем.
В чём же дело? Собака зарыта в том, как принудительно завести
dhandler; это значит, каким образом «вкинуть» его в
CGI. Несмотря на то, что данный пример такого проброса не претендует на звание идеального, но там, где не требуется обработка 1000 одновременных запросов, он справляется вполне достойно. Вот рецепт:
#!/usr/bin/perl
#Файл: mason_handler.cgi ( cgi handler для обработки компонент, auto-, dhandler’a )
use HTML::Mason::CGIHandler;
use lib '/path/to/lib '; # Абсолютный путь к библиотекам Ваших модулей
use YourModule1; # Ваш модуль1
use YourModule2; # Ваш модуль2
use utf8;
# Установка для принудительного вызова dhandler
$ENV{PATH_INFO} = '/path/to/DocumentRoot/dhandler';
my $h = HTML::Mason::CGIHandler->new(
data_dir => '/path/to/mason data dir',
comp_root => '/path/to/component/root',
allow_globals => [qw($globalscalar)],
);
$h->handle_request;
Что ещё надо было бы сказать про HTML::Mason
Данный раздел помещён здесь далеко не случайно, а скорее как «крик души». Наверное, многие разработчики, которые имеют работы с неанглоязычными данными сталкивались с различного рода казусами ввода-вывода и последующего отображения языков, отличных от английского.
Начнём с классики, которая в данном случае представляется
UTF-8. В теории (perlunicode, etc) говорится о встроенных классах символов типа “
\p{InBasinLatin}”, “
\p{InCyrillic}” и так далее, которые в связке с оператором ‘
qr()’ могут, и действительно делают, чудеса. Также нелишним будет вспомнить и старушку ‘
quotemeta()’, которая и сейчас бывает полезной; однако, когда дело доходит до использования всего этого добра в
HTML::Mason, то всё оказывается не так гладко.
Приведём пример: у вас есть таблица
mysql, которую вы используюте исключительно с ‘
SET NAMES utf8’ (ну, чтобы попроще было со смешанными текстами и сборными страницами) и которая также сама имеет там, где надо ‘
CHARSET=utf8 COLLATE=utf8_unicode_ci’; затем, вам где-то в форме у пользователя надо бы «почистить» ввод с помощью всеми любимой ‘
s///go’ (само собой разумеется, что у вас все страницы содержат валидный
XHTML с мета-тэгом ‘
charset=utf-8’, указанным явно или через ‘
headers_out()’ от
HTML::Mason), но почему-то «очистка» не работает как надо! Вы лихорадочно пытаетесь задействовать, опять же согласно стандартной документации
Perl, до боли знакомую прагму ‘
utf8’ прямо в компоненте... теперь с регулярными выражениями всё, кажется, в порядке, но при этом как-то странно выглядит контент на сборной странице. Вот вроде бы появился свет в конце туннеля, вы «находите» спасительный модуль Encode с его “
decode(), encode()” и пытаетесь «нормализовать» входные данные, поступающие прямо из формы... Результат тот же, и не тот, что надо.
Возможно, ваша собственная история несколько иная, но мораль сей байки такова: все данные, которые соответствуют
UTF8, во внутреннем представлении
Perl практически всегда отличаются от приходящих из интерфейса; единственное назначение такой формы данных, хотя справедливости ради надо сказать, что они вполне пригодны для отображения в
браузере, это скармливание их регулярным выражениям, которые, в свою очередь, если составлены верно, с радостью их обработают в таком виде и выдадут вам правильный (читай – ожидаемый) результат. Во всех же остальных местах вашего драгоценного ресурса их никогда нельзя выпускать «на волю», в противном случае, будет беда: явное включение
UTF8 каким-либо образом хотя бы в одной из компонент
HTML::Mason приводит к тому, что данные из этой компоненты отображаются правильно, а все остальные, как в нашем случае со сборной страницей, будет «не так».
Проблема обрела форму, но где же решение? Здесь также нелишне вернуться к первоисточникам: там настоятельно советуют следовать старому принципу – «разделяй и властвуй», что в применении к настоящей проблеме можно перефразировать следующим образом. Все процедуры, которые требуют сугубо юникодовской трактовки данных при обработке исключительно средствами языка
Perl, должны находиться только в модулях, а не в компонентах; там же можно использовать инструменты, подобные
Encode::encoded/decoded(“uf8”, $datum). Это одно из, слава нашему Богу, немногих ограничений при планировании приложений, разрабатываемых с помощью
HTML::Mason.
Это всё было «внутри», теперь же несколько слов про то, что возможно сделать «снаружи». В
HTML::Mason имеются встроенные
*escape* функции; не стоит, наверное, цитировать авторов, надо лишь сделать несколько замечаний относительно вещей, подобных ‘
|h’.
На самом деле, если у Вас англоязычный ресурс, то повода для беспокойств нет. Однако в противном случае, если Вы используете кодировку
unicode (utf8), следующий код поможет решить проблему с организацией литерального представления данных пользователя. Это нужно, например, тогда, когда на Вашем ресурсе пользователи осуществляют ввод посредством html form. Если пользователи введут данные вместе с
HTML – тэгами, тогда при отображении этих данных, чтобы не нарушился интерфейс ресурса нелишним будет следующее:
Файл: autohandler
……
% $m->interp->set_escape( h => \&HTML::Mason::Escapes::basic_html_escape );
% $m->call_next();
……
Файл: <Ваша компонента>
……
<% $htmlstring | h %>
……
Пример сборки ресурса
Здесь мы хотели бы проиллюстрировать на простом примере всё, о чём было сказано выше.
В данном примере мы создаём небольшой ресурс, составными частями которого будут:
- модуль, основным назначением которого будет сопряжение с БД;
- autohandler и dhandler
- набор компонент для сборки нехитрого интерфейса.
Замечания и комментарии будут даваться по ходу представления исходного кода ресурса.
Пример приложения можно скачать
здесь (~ 10 Kb).