1 заметка с тегом

thttpd

«Парсер» студии Лебедева и 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.