前回の
さまざまなPlack::Middleware
Plack::Middlewareの3パターンについて具体的なモジュールを見ながら理解を深めたところで、
なお、
開発を捗らせるPlack::Middleware
プロダクション環境では必要ありませんが、
DebugLogging──コンソールにデバッグ情報を出力する
Plack::Middleware::DebugLoggingは、
enable "DebugLogging";たとえば、Content-type: application/でJSONをリクエストすると、
$ curl -X POST -H "Content-type: application/json" -d '{"user":123}' http://127.0.0.1:5000/?foo=bar上記のようなリクエストを投げると、
"POST" request for "/" from "127.0.0.1"
Request Headers:
.-----------------+-----------------------------------.
| Header Name     | Value                             |
+-----------------+-----------------------------------+
| Accept          | */*                               |
| Host            | 127.0.0.1:5000                    |
| Content-Length  | 12                                |
| Content-Type    | application/json                  |
'-----------------+-----------------------------------'
Query Parameters are:
.-----------------------+-----------------------------.
| Parameter             | Value                       |
+-----------------------+-----------------------------+
| foo                   | bar                         |
'-----------------------+-----------------------------'
application/json encoded body parameters are:
{
  user => 123
}StackTrace::LinkedSource──スタックトレースからソースをブラウザで表示する
Plackの開発環境では、
enable "StackTrace::LinkedSource",
    lib => ['/your/app/lib', @INC]; 
ローカルの実行環境ならソースコードを参照するのも難しくないと思いますが、
HTTPヘッダを扱うPlack::Middleware
WebアプリケーションでHTTPヘッダを扱う場面はたくさんあります。そうしたものの中には、
ETag──ETagヘッダを自動で付与する
Plack::Middleware::ETagは、
enable "ETag";アプリケーションで静的ファイルを配信している場合は、
ConditionalGET──ステータスコード304に対応する
Plack::Middleware::ConditionalGETは、
enable "ConditionalGET";CrossOrigin──CORSに対応する
Plack::Middleware::CrossOriginは、
enable "CrossOrigin",
    origins => '*',
    methods => ["GET", "POST"],
    max_age => 60*60*24*30;CORSに対応するヘッダは、
プロダクションに常時投入したいPlack::Middleware
ここでは、
次に紹介する2つのPlack::Middlewareは、
MemoryUsage──メモリの使用量を見る
Plack::Middleware::MemoryUsageは、
enable "MemoryUsage",
    callback => sub {
        my ($env, $res, $before, $after, $diff) = @_;
        my $worst_count = 3;
        for my $pkg (sort {
                $diff->{$b} <=> $diff->{$a}
            } keys %$diff) {
            warn sprintf("%-32s %8d = %8d - %8d[KB]\n",
                         $pkg,
                         $diff->{$pkg}/1024,
                         $after->{$pkg}/1024,
                         $before->{$pkg}/1024,
                        );
            last if --$worst_count <= 0;
        }
    };出力内容はcallbackオプションにコードリファレンスを自分で書く必要がありますが、
B::PVOP             0 =       5 -       4[KB]
B::PVIV             0 =       2 -       1[KB]
B::IV               0 =      10 -      10[KB]
IO::Socket::INET    0 =     137 -     137[KB]
Apache2::Status     0 =      18 -      18[KB]
Symbol              0 =      19 -      19[KB]Profiler::NYTProf──プロファイリングを取得する
Plack::Middleware::Profiler::NYTProfは、
enable "Profiler::NYTProf",
    enable_profile => sub { $$ % 2 == 0 },
    env_nytprof => 'start=no:addpid=0',
    enable_reporting => 0;prefork型のアプリケーションにおいて、
Plack::Middlewareの利用時のTips
さて、
Plack::Middlewareのロード
Plack::Middlewareのロード方法は2つあります。
1つ目は、
use Plack::Middleware::ETag;
my $app = sub { [ 200, [], ["OK"] ] };
$app = Plack::Middleware::ETag->wrap(
    $app,
    file_etag => [qw/size/],
);2つ目は、
use Plack::Builder;
builder {
    enable "ETag", file_etag => [qw/size/];
    sub { [ 200, [], ["OK"] ] };
};DSLを使ったロード方法はuseを書く必要がなく、"Plack::Middleware::"の部分を省略できるなど、
また、plackupコマンドでも直接使えるので、
$ plackup -e 'enable "ETag"; sub { [200, [], ["OK"]] }'新しいミドルウェアを試してみる場合などに、plackupコマンドでさくっと試すというのが簡単でお勧めです。
開発環境とプロダクション環境での切り替え
開発環境とプロダクション環境で利用するPlack::Middlewareを切り替えたい場合は、
use Plack::Builder;
builder {
    enable_if {
        $ENV{PLACK_ENV} ne "production"
    } "DebugLogging";
    sub { [ 200, [], ["OK"] ] };
}ただし、
気になる人は、
if ($ENV{PLACK_ENV} ne "production") {
    enable "DebugLogging";
}実行条件の複雑化への対処
enable_
use Plack::Builder;
use Plack::Builder::Conditionals;
builder {
    enable match_if addr(
        ['192.168.0.0/24', '127.0.0.1']
    ), "ReverseProxy";
    $app;
};Plack::Middlewareのロード順と実行順序
先述したとおりPlack::Middlewareには、
次の2つのPlack::Middlewareがあるとします。1つ目はPlack::Middleware::Fooで、$self->appの前後で標準出力にミドルウェア名を出力するだけです。
package Plack::Middleware::Foo;
use parent qw( Plack::Middleware );
sub call {
    my ($self, $env) = @_;
    say "Before Foo";
    my $res = $self->app->($env);
    say "After Foo";
    return $res;
}package Plack::Middleware::Bar;
use parent qw( Plack::Middleware );
sub call {
    my ($self, $env) = @_;
    say "Before Bar";
    my $res = $self->app->($env);
    say "After Bar";
    return $res;
}この2つのミドルウェアを次のように利用します。Foo➡Barの順にenableしています。
use Plack::Builder;
builder {
    enable "Foo";
    enable "Bar";
    sub { say "App"; [ 200, [], ["OK!"] ] };
};これを実行すると、
Before Foo
Before Bar
App
After Bar
After FooenableしたのはFoo➡Barの順でしたが、$self->appのあとに書かれたPlack::Middlewareの処理は、
<続きの
本誌最新号をチェック!
WEB+DB PRESS Vol.130
2022年8月24日発売
B5判/
定価1,628円
ISBN978-4-297-13000-8
- 特集1
 イミュータブルデータモデルで始める
 実践データモデリング
 業務の複雑さをシンプルに表現!
- 特集2
 いまはじめるFlutter
 iOS/Android両対応アプリを開発してみよう 
- 特集3
 作って学ぶWeb3
 ブロックチェーン、スマートコントラクト、 NFT 


