PSGIミドルウェアを利用する
PSGIミドルウェアはアプリケーションと同様にコードリファレンスとして実装されますが,いちいち.psgiファイルに記述するのはあまり効率が良くありませんし,再利用性もありません。そこでPlackにはミドルウェアをモジュールとして利用するためのベースクラスPlack::Middlewareや,それを利用して実装された各種ミドルウェアが同梱されています(注2)。
ここでは,これらのミドルウェアを利用して先ほどのTatsumakiアプリケーションを拡張してみましょう。
- 注2)
- そのほか,コアには含まれないミドルウェアも各種CPANモジュールとしてアップロードされています。
Auth::Basic
PSGIアプリケーションに簡単なHTTP認証機能を付けるミドルウェアがAuth::Basicです。容易に拡張できるコールバックインタフェースを持っているため,データベースやLDAP(Lightweight Directory Access Protocol)などとの連携もできます。
まずは,先ほどのhello.psgiを開き,ミドルウェアを利用するコードを追加します。リスト5のように,Plack::Middleware::Auth::Basicをロードし,wrapメソッドを使ってPSGIアプリケーションのコードリファレンス($app->psgi_app)に認証機能を追加します(②)。authenticatorはユーザ名,パスワードを受け取り,それが正しいかどうかを返すコールバック関数になります。また,Helloハンドラ内でも,認証されたユーザを$self->request->userから取得して画面に表示(①)するようにしてみます。
リスト5 Auth::Basicの追加
use strict;
package Hello;
use parent 'Tatsumaki::Handler';
sub get {
my $self = shift;
$self->write("Hello ", $self->request->user); ……①
}
use Tatsumaki::Application;
my $app = Tatsumaki::Application->new([
'/hello' => 'Hello',
]);
use Plack::Middleware::Auth::Basic; ┐
$app = Plack::Middleware::Auth::Basic->wrap( │
$app->psgi_app, │
authenticator => sub { │②
my($user, $pass) = @_; │
return $user eq 'admin' && $pass eq 'gihyo';┘
},
);
ブラウザでhttp://localhost:5000/helloをもう一度開いてみましょう。図6のように認証ダイアログが表示されるはずです。ここではコードに記述したように,ユーザ名「admin」,パスワード「gihyo」だけが正しい入力ペアとなっています。それ以外の値を適当に入力しても,再度ダイアログが表示されるだけでしょう。正しいパスワードを入力すれば,「Hello admin」と認証によって取得したユーザ名が出力されます。
Auth::BasicミドルウェアはCPANモジュールのAuthen::Simpleのインタフェースにも対応しているため,LDAPや.htpasswdファイルなどによる認証と簡単に連携できます。詳しくはオンラインドキュメントを参照してください。
Plack::Builder
先ほどの例では,ミドルウェアを通常のPerlモジュールのようにuseし,wrapメソッドを呼ぶことでミドルウェアを追加しました。この方法では利用するミドルウェアを増やしていく場合などに記述が長くなりがちで,ミドルウェアの実行順序などが直感的でないという問題があります。そこで用意されているのがPlack::BuilderモジュールによるDSL(Domain Specific Language,ドメイン特化言語)です。
Auth::Basicを利用したミドルウェアの例は,Plack::Builderを利用するとリスト6のように記述できます。ラップされるアプリケーションをbuilder { }で囲み,その上にenableミドルウェア名,オプション...;のようにスタックしていくイメージです。ミドルウェア名の「Plack::Middleware::」部分は省略できますし,モジュールはBuilderによって自動的にロード(require)されますので,記述を大幅に簡潔化できます。
リスト6 Builderによるミドルウェアの記述
# $appまではリスト5と同様
use Plack::Builder;
builder {
enable "Auth::Basic", authenticator => sub { ... };
$app->psgi_app;
};
たとえば,ここでは詳細を省きますが,スタティックファイルを配信するミドルウェアStaticやアプリケーションの実行時間をX-Runtimeヘッダに挿入するRuntimeミドルウェアと組み合わせるとリスト7のように書くことができます。図4で見たようにアプリケーションが真ん中にあるとすれば,builderの中で下の行にありアプリケーションに近いほうが,真ん中に近い位置にあることになります。よって,この.psgiファイルを実行すると,Auth::Basic⇒Static⇒Runtime⇒Tatsumakiアプリケーション⇒Runtime⇒Static⇒Auth::Basicの順番で処理が実行されます。ミドルウェアごとにアプリケーションの前に実行されるもの(認証など),後に実行されるもの(出力ヘッダの挿入など)に種類が分かれていますので,ドキュメントなどを参照して,どの順番が最適かを検討してください。
リスト7 ミドルウェアの追加
# $appまではリスト5と同様
use Plack::Builder;
builder {
enable "Auth::Basic", authenticator => sub { ... };
enable "Static", path => qr/^\/images/, root => "/images";
enable "Runtime";
$app->psgi_app;
};
そのほかのミドルウェア
紙幅の都合ですべては紹介できませんが,PlackコアやCPANには便利な各種ミドルウェアがアップロードされています。
Session
Sessionミドルウェアはフレームワークにセッション管理機能を追加します。多くのフレームワークが自前でセッション管理を実装している場合がほとんどのため,執筆時点ではあまりメリットがありませんが,フレームワークからこのPlack::Middleware::Sessionを利用するためのアダプタを記述すれば,各種フレームワークでセッションを共有する,といったことが容易にできるようになります。SessionミドルウェアはCookieによりID管理を行い,ストレージには各種ファイルやmemcachedといったキャッシュバックエンドが利用可能です。
Debug
PythonのDjangoプラグインであるdjango-debugtoolbarやRackのミドルウェアrack-bugにインスパイアされて作成したミドルウェアがDebugです。このミドルウェアを有効にすると,HTMLページの右側にパネル(図7)が表示され,リクエストヘッダやレスポンス,各種フレームワークのログなどをクリックして見ることができます。開発時にはとても有用なミドルウェアでしょう。

