Pull to refresh

PSGI — интерфейс между web-серверами и web-приложениями на perl

Perl *
Не так давно появилась спецификация интерфейса между web-серверами и приложениями/фреймворками на perl PSGI — Perl Web Server Gateway Interface Specification. PSGI добавляет слой абстракции, позволяющий не заботиться о конкретном способе подключения к web-серверу, и реализовать единственный интерфейс для спецификации. Запустить такое приложение можно на cерверах, поддерживающих PSGI — на данный момент это Plack (набор серверов и утилит), nginx (с патчем для поддержки PSGI и встроенным perl) и Apache с mod_psgi.

Приложения


PSGI-приложение представляет собой функцию, принимающую в качестве аргумента ссылку на хэш с переменными окружения, и возвращающую ответ.

Запрос

Хэш, передаваемый в приложение, содержит переменные, имена которых аналогичны именам заголовков в CGI — REQUEST_METHOD, SCRIPT_NAME, QUERY_STRING и т.д., а также заголовки из HTTP-запроса (начинаются с HTTP_, например HTTP_HOST). Кроме этого, хэш должен содержать PSGI-специфичные переменные:
  • psgi.version: Ссылка на массив [1,0], содержащий версию PSGI.
  • psgi.url_scheme: http или https, в зависимости от запроса.
  • psgi.input: поток ввода.
  • psgi.errors: поток для вывода ошибок.
  • psgi.multithread: true, если приложение может быть вызвано в другом потоке того же процесса.
  • psgi.multiprocess: true, если приложение может быть вызвано в другом процессе.
Также хэш может содержать дополнительные переменные:
  • psgi.run_once: true, если ожидается (но не гарантируется), что приложение будет вызвано только один раз до завершения процесса (обычно true только если приложение подключено к серверу через CGI).
  • psgi.nonblocking: true, если приложение вызывается в event loop.
  • psgi.streaming: true, если сервер поддерживает отложенные ответы и streaming.
Приложение может проанализировать переменные окружения, и учесть особенности сервера либо завершить свое выполнение, если сервер не поддерживает то, что нужно приложению (например, запускаемое приложение неблокирующее, а сервер написан в синхронном стиле).

Ответ

В общем случае приложение должно вернуть ссылку на массив из трех элементов — HTTP-код ответа, заголовки и тело ответа. HTTP-код ответа должен быть целым числом не менее 100. Заголовки передаются в виде ссылки на массив, причем заголовок Content-Type должен присутствовать обязательно (кроме ответов 1xx, 204 или 304). Телом ответа может являться ссылка на массив строк (или весь ответ без построчного разделения), либо IO::Handle-подобный объект или файловый дескриптор. Если требуется отложенный ответ, приложение может вернуть функцию, в которую будет передан колбэк для ответа.

Пример приложения

Так выглядит простейшее PSGI-приложение:
sub {[200, ['Content-Type' => 'text/plain'], ['Hi, ' . shift->{REMOTE_ADDR}]]}


Middleware


Middleware похоже на обычное приложение, но принимает 2 аргумента — переменные окружения и ответ PSGI-приложения. Middleware может применяться для анализа этих данных (например, обычное ведение access log) или их модификации. Вот пример middleware, добавляющего в ответ заголовок X-PSGI-Used:
my $app = sub {[200, ['Content-Type' => 'text/plain'], ['Hi, ' . shift->{REMOTE_ADDR}]]}<br/>
my $middleware = sub {<br/>
    my $env = shift;<br/>
    my $res = $app->($env);<br/>
    push @{$res->[1]}, 'X-PSGI-Used' => 1;<br/>
    return $res;<br/>
};

Для Plack на CPAN существует довольно большой набор разнообразных middleware.

Серверы


Сервер обеспечивает запуск PSGI-приложения и должен составлять хэш с переменными окружения и передавать его в приложение, а также обрабатывать ответ. Сейчас существует несколько PSGI-серверов:
  • Plack — набор middleware и серверов, в большинстве своем являющихся врапперами над существующими Perl-модулями. Кроме того, существует несколько серверов в том же пространстве имен, не присутствующих в составле дистрибутива Plack на CPAN: AnyEvent, FCGI::EV, Danga::Socket, Coro, POE и ServerSimple. Запустить PSGI-приложение на Plack просто:
    plackup --server Coro --port 9090 --host 127.0.0.1 test.psgi
  • nginx с патчем для поддержки psgi
  • mod_psgi для Apache
  • Perlbal
  • некоторые другие серверы
Отдельно хочу отметить Plack::Server::AnyEvent и Plack::Server::Coro — в этих серверах реализована поддержка файлового AIO, поэтому небольшие неблокирующие PSGI-приложения на их основе можно использовать для раздачи статики с полным отсутствием блoкировок, пока поддержка AIO не готова в nginx.

Поддержка фреймворками


Сейчас есть поддержка PSGI во всех популярных web-фреймворках: Catalyst, CGI::Application, HTTP::Engine, Dancer, Mason, Squatting, Continuity, Maypole, Tatsumaki

Ссылки


Сайт PSGI/Plack
Спецификация PSGI на CPAN
PSGI::FAQ
Plack на CPAN
Tags:
Hubs:
Total votes 21: ↑17 and ↓4 +13
Views 4.8K
Comments Comments 83