PSGI/Plack勉強会

PSGI/Plack勉強会を開きました(ひとりで)。資料はGitHubにあげてあります。いろいろまとめ書き足りてないのですが、自分的には納得したので満足してしまいました。

以下にもコピペ。

PSGI/Plackとは?

  • PSGI = Perl Web Server Gateway Interface Specification
    • WebサーバとWebアプリケーションとの間のインタフェイス仕様
  • Plack = PSGIのリファレンス実装
    • PSGI実装のひとつ(とはいえ、やたら気合いの入った感じになってるけど)
    • PSGI != Yet Another WAF
    • PSGI != Plack

PSGI策定の背景

  • 各Webアプリケーションフレームワークがバラバラに実装していた、WebサーバとWebアプリケーションとのインタフェイスを統一したい。
  • そのためには、仕様と実装の区別を明確に行う必要がある。
  • そこで、仕様としてPSGIが定められ、そのリファレンス実装としてPlackが開発されている。
  • インタフェイス仕様と実装を切り分けることにより、Webアプリケーションフレームワーク開発者は、より本質的な実装に注力できる。

PSGIプロトコル概略

ref: http://github.com/miyagawa/psgi-specs/blob/master/PSGI.pod

.------------------------------------------------------------.
|                        Application                         |
'------------------------------------------------------------'
|
.------------------------------------------------------------.
|                           WAF                              |
'------------------------------------------------------------'
| passes $app as a coderef
.------------------------------------------------------------.
|                    PSGI implementation                     |
'------------------------------------------------------------'
|                   | request as an $env   |
.------------------. .------------------. .------------------.
|     mod_perl     | |      FastCGI     | |    Pure  Perl    |
'------------------' '------------------' '------------------'
|                   |                      |
.------------------------------------------------------------.
|                         Request                            |
'------------------------------------------------------------'

PSGIにおけるアプリケーションとは

  1. 環境変数PSGIによる拡張あり)をハッシュとして受け取り、
  2. レスポンスをPSGIに定められた形式の配列リファレンスで返す

という仕様を満たすコードリファレンス(詳細は後述)。

Plack

  • PSGIのリファレンス実装
  • 現在、以下のバックエンドに対応
    • Apache2
    • CGI
    • Coro
    • Danga::Socket
    • FCGI
    • Mojo
    • ReverseHTTP
    • ServerSimple
    • Standalone
    • nginxにも限定的に対応
    • 今後、GAE, mod_perliteにも対応予定とのこと

Hello World

  • ハンドラ = coderefを.psgiファイルに定義する
  • plackupを使い、plackを起動する

config/hello_world.psgi

my $handler = sub {
return [
200,
[ "Content-Type" => "text/plain", "Content-Length" => 11 ],
[ "Hello World" ],
];
};

plackの起動

perl -Imodules/Plack/lib modules/Plack/scripts/plackup -app config/hello_world.psgi

Hello World (2)

plackupの行っていること:

  1. config/hello_world.psgiをロード。
  2. Plack::Loaderにより適切なサーバ実装が選択される。
    • この場合、Plack::Impl::StandAloneが使われる。plackupへの–implオプションで変更可能。
  3. 選択されたPlack::Impl::*に$handlerがわたされ、アプリケーションが実行される。

Plackを使ってWAFを作ろう (1)

最低限必要なもの:

  • 環境変数を受け取り、レスポンスをPSGI形式で返すコードリファレンス
  • 受け取った環境変数(リクエスト)を元に、あれこれする箇所(WAFの勘所)
  • psgiファイル

Plackを使ってWAFを作ろう (2)

環境変数を受け取り、レスポンスをPSGI形式なコードリファレンスとしてハンドラ。

package MyWAF::Handler::PSGI;
use strict;
use warnings;
use Carp qw(croak);
use UNIVERSAL::require;
sub handler {
my ($class, $app) = @_;
qroak qq{no such app: $app} if !$app->use;
    sub {
my $env = shift;
$app->run($env);
};
}
!!1;

Plackを使ってWAFを作ろう (2)

受け取った環境変数(リクエスト)を元に、あれこれする箇所(WAFの勘所)。

package MyWAF;
use strict;
use warnings;
sub run {
my ($class, $env) = @_;
# $envからリクエストオブジェクトを生成
# どのコントローラ、アクションにdispatchするかを決定
# コントローラ実行
# ビューをレンダリング
return $response->result;
# レスポンスを以下のような形式の配列リファレンスとして返す
# [
#     200,
#     [
#         'Content-Type' => 'text/html',
#         # ...
#     ],
#     [ 'Hello World' ]
# ]
}
!!1;

Plackを使ってWAFを作ろう (3)

早速使ってみる。MyAppを作成。

package MyApp;
use strict;
use warnings;
use base qw(MyWAF);
!!1;

Plackを使ってWAFを作ろう (4)

Plackアプリケーションを起動するためのpsgiファイル。

use MyWAF::Handler::PSGI;
my $handler = MyWAF::Handler::PSGI->handler('MyApp');

Plackを使ってWAFを作ろう (5)

MyAppをCGI上で動作させる。

#!/usr/bin/env perl
use strict;
use warnings;
use Plack::Impl::CGI;
my $app = do 'config/myapp.psgi';
Plack::Impl::CGI->new->run($app);

Plackを使ってWAFを作ろう (6)

MyAppをmod_perl上で動作させる。

<Locaion />
SetHandler  perl-script
PerlHandler Plack::Impl::Apache2
PerlSetVar  psgi_app /path/to/myapp.psgi
</Location>

Plackを使ってWAFを作ろう (7)

続きはGitHubで。

RidgeのPSGI/Plack対応

id:hakobe932が対応つつあります。

  • Ridgeのplackブランチ

まとめ

  • PSGIの仕様はシンプル。
  • Plackという実装もあるので、サーバ実装の差異にまつわる面倒なことをお任せできて、簡単にWAFを作れる。
  • お膳立ては整っているので、いけてるWAFにするのはWAF開発者のセンス次第。

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


© 2020 栗林健太郎

Theme by Anders NorénUp ↑