«Парсер» студии Лебедева и thttpd

Сегодня потратил часть дня, чтобы выяснить, что Парсер не заработает с thttpd.

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

Что-то у меня с nginx в последнее время любовь как-то не складывается.

У меня Ubuntu 10.04, поэтому я всё поставил из пакетов, Парсер в том числе, пакет неофициальный, я его нашёл в разделе прислали пользователи.

После того как я всё настроил, ничего не заработало. Отладка через strace быстро показала, что Парсер падает. Я его перекомпилировал. Если будете перекомпилировать, вот мой рецепт.

Я поставил следующие пакеты (легко допускаю, что где-то поставил лишнего, так как ориентировался по названиям): libgmime2.1-dev libgmime-2.4-2 glibc-2.10-1 libgc1c2 bison.

В каталог /opt/pcre-8.12 я положил свежую версию PCRE, в /opt/pcre лежит скомпилированная версия. Строка компиляции получилась вот такая:

CPPFLAGS='-I/opt/pcre-8.12 -I/opt/pcre/include/' \
./configure --prefix=/opt/parser3/ --with-shared-gc --with-static-pcre=/opt/pcre
make
sudo make install

После того как я стал пользоваться собранным мною Парсером, что-то в браузер я получил, но всё было не то. Причём при запуске из консоли, я получал на экран результат работы скрипта.

Тут я догадался (поскольку в консоли не видел HTTP-заголовков), что Парсер имеет какой-то механизм, который должен его переключать из режима командной строки в режим CGI и обратно. Из вида протокола CGI понятно, что это какие-то переменные окружения.

Я создал небольшой shell-скрипт, в который накидал разных переменных окружения, необходимых по стандарту для CGI и подбором выяснил, что для Парсера критично наличие переменных GATEWAY_INTERFACE, SCRIPT_NAME, PATH_INFO и PATH_TRANSLATED. Вот небольшой пример:

if(cgi) {
                // few absolute obligatory
                const char* path_info=getenv("PATH_INFO");
                if(!path_info)
                        SAPI::die("CGI: illegal call (missing PATH_INFO)");
                const char* script_name=getenv("SCRIPT_NAME");
                if(!script_name)
                                SAPI::die("CGI: illegal call (missing SCRIPT_NAME)");
                // … ещё много кода …
        }

При помощи CGI, написанного на bash, я выгрузил все переменные окружения, которые предоставляет thttpd (у меня версия 2.25b), оказалось, что двух последних переменных в дампе нет. Причём в интернете эта проблема уже поднималась (правда без связи с Парсером) и была успешна разрешена авторами thttpd. Наверное в последней версии что-то сломали.

Добавлено: я что-то явно делаю не так. Я попробовал ещё сервер mini-httpd, там в changelog есть такая фраза: «Added PATH_INFO to CGI environment», но я опять же не вижу эту переменную в окружении. В исходниках так же упоминаются обе переменных «PATH_…».

Добавлено ещё позже: так, по коду выходит следующее: если mini-httpd или thttpd находит файл по URL на файловой системе сразу, то PATH-переменные не заполняется, но заполняется SCRIPT_NAME, если не находит, то алгоритм отрезает путь до первого слеша и кладёт орезанное в PATH_INFO, формируя PATH_TRANSLATED из этого пути, присоединяя к нему рабочий каталог.

При этом куда-то пропадает SCRIPT_NAME, в коде я ещё не нашёл куда и почему. Но, похоже, для Парсера mini-httpd и thttpd (у них один автор) не подойдут.

Чтобы понимать:

http://example.org/cgi-bin/test.cgi — формируется SCRIPT_NAME, но не PATH_INFO и PATH_TRANSLATED
http://example.org/cgi-bin/test.cgi/ — формируется PATH_INFO и PATH_TRANSLATED, но не SCRIPT_NAME

И ещё позднее: попробовал веб-серверы Boa, Bozohttpd и Cherokee. Парсер с ними не заработал, причина та же — нехватает переменных. Очень похоже, что Парсер сильно неправ в своей трактовке протокола CGI.

4 комментария

«Парсер» студии Лебедева и nginx

Смог запустить Парсер на nginx. Поставил FastCGI-сервер SimpleCGI, он принимает на вход FastCGI-запрос и запускает по нему CGI-программу. Написан на Перле, который я хорошо знаю, поэтому мне сразу видно как его можно настроить. Настройки nginx получились следующие:

server {
        listen 80;

        server_name  parser.internal;
        set $root /var/www/parser;
        root $root;

        location ~ \.(p|cgi)$ {
            include fastcgi_params;
            fastcgi_pass unix:/var/www/cgiwrap-dispatch.sock;
            fastcgi_param  SCRIPT_NAME  $fastcgi_script_name;
            fastcgi_param  PATH_INFO    $fastcgi_script_name;
            fastcgi_param  PATH_TRANSLATED $root$fastcgi_script_name;
            fastcgi_param  SCRIPT_FILENAME  $root$fastcgi_script_name;
        }
}

SimpleCGI после запуска создаёт файловый сокет «cgiwrap-dispatch.sock» к которому и обращается nginx.

Причём, что интересно, с SimpleCGI спокойно работает и Парсер из пакета, на который я жаловался, что он падает из-под thttpd.

Добавлено позже: если нужно указать путь до auto.p, то можно добавить «fastcgi_param CGI_PARSER_CONFIG путь/до/auto.p».

2 комментария

Заведения в Симферополе

На светлом столе лежат журнал «Юность» №5 за 1981 год с иллюстрацией деревьев и домиков и толстая книга «Детская Энциклопедия» в жёлтой обложке с силуэтом ребёнка.
Уютный уголок с белым стеллажом, заполненным книгами, деревянным столом, зелёным диваном с декоративными подушками и цветочными обоями на стене.
Старая книга М. Горького «Счетъ» с портретом автора на обложке лежит на столе рядом с раскрытой книгой и чеком.
Уютный интерьер кафе с кирпичной аркой, патинированными обоями, подвесными светильниками и портретом на стене; видна часть зала с круглыми столами и креслами.

Я третий раз в Симферополе и он мне нравится всё больше и больше. Говорят на окраинах тут всё очень печально, зато в центре очень хорошо. Для такого небольшого города количество заведений где можно вкусно и приятно поесть довольно приличное.

Утром завтракали в «Горьком» — ресторанчике, посвящённом литературе и Горькому, интерьер заставлен советскими ещё книгами, стилизация отлично выдержана. Счёт приносят внутри книги (есть на снимках).

Прекрасно осознаю, кстати, где таятся недостатки города, но я там не бываю, к чему мне? Я же тут не живу, буду радоваться тому, что турист.

Выяснил сколько примерно стоит квартира. Однокомнатные продаются примерно за $36—50K, причём зависимость чуть не чёткая — метр стоит около $1K. Жаль, что не сходил в краеведческий музей, если приеду ещё раз, надо будет посетить.

Завтра уже улетаем, в середине дня.

19 комментариев