CGI::PSGIの利用_第3回 ログ集計グラフ化アプリの紹介

6.アプリケーションの概要

 第2回目ではマルチアプリケーションフレームとして作ったpsgiファイルを紹介しました。第3回目ではログ集計グラフを表示する簡単なアプリケーションの実体を紹介します。このアプリケーションはパッケージとして作成し、CGI::PSGIを利用しています。といってもCGI.pmの利用とあまり変りません。newのreturn行と、イメージ出力関数を呼びPSGI規格のretunをするto_appというメソッドがPSGIに特化していると言える部分です。
 初めて作ったPSGIアプリなわけですが基本的にはこんな感じかなあという程度の例です。なお、触れてませんが、GD、GD::Graph::mixed、GD::Graph::pieは、他の図形アプリを作るかもしれないので第2回で紹介したマルチフレームであるpsgiファイル内でuseしてあります。

7.Analyz.pmの紹介

package Sitelog::Analyz;
# クラス変数定義
our (
・・・・・・・・・・・・・
PSGI化前のmainルーチンで使用していた
グローバルスコープの変数群をクラス変数とした。
・・・・・・・・・・・・・
$Q,$im
);
# オブジェクトメソッド
sub new {
# アプリケーションオブジェクトの生成とメンバーの初期化
my ($class,$q) = @_;
$Q = $q; # CGI::PSGI オブジェクトリファをクラス変数にコピー
my @headers = $Q->psgi_header('text/html');
my $self = {
Status => $headers[0], # Status--200とか
CT => $headers[1], # Content-Type
BODY => '<html><body>Hello PSGI 1234567890</body></html>',
# Dummy BODY
@_,
};
return bless $self,$class;
}
sub to_app {
my $self = shift;
my @headers = $Q->psgi_header('image/png');
$self->status($headers[0]); #
$self->ct($headers[1]); # Content-Typeをイメージに変更
$self->body(makeimage());
# 生成したグラフイメージを返すメソッドを引数にしてメンバー変数BODYの値を更新
return [$self->{Status},$self->{CT},[$self->{BODY}]];
# PSGI規格の3点セットを返却
}
sub status { # メンバー変数Statusの値更新メソッド
my $self = shift;
if( @_ ){ $self->{Status} = shift }
return $self->{Status};
}
sub ct { # メンバー変数CTの値更新メソッド
my $self = shift;
if( @_ ){ $self->{CT} = shift }
return $self->{CT};
}
sub body { # メンバー変数BODYの値更新メソッド
my $self = shift;
if( @_ ){
$self->{BODY} = shift;
}
return $self->{BODY};
}

#************** Main **************
sub makeimage { # image body 生成
# PSGI化前の元々のmainルーチン
# GD::Graphを駆使した内容
# 「Plack::APP::CGIBinの利用」参照
・・・・・・・・・・・・
&initgd0; # GD初期化
・・・・・・・・・・・・
my $method = $Q->request_method();
if(uc($method) eq 'GET'){ # リクエストチェック
if($Q->param('act') eq 'disp_grp'){
$rw = &set_logdata;
if($rw != 0){return err_wr("set_logdata Error")}; #Error
return disp_grp($Q->param('page'));
}elsif($Q->param('act') eq 'disp_grp_pie'){
$rw = &set_logdata_pie;
if($rw != 0){return err_wr("set_logdata_pie Error")}; #Error
return disp_grp_pie($Q->param('page'));
}else{
return err_wr("Call Error1");
}
}else{
return err_wr("Call Error0");
}
}

#**** makeimage内で呼ばれるサブルーチン群 ****
#   「Plack::APP::CGIBinの利用」参照

sub disp_grp_pie($){ # 円グラフ生成
・・・・・・・・・・・・・
}
#**************
sub disp_grp($){ # 複合棒グラフ生成
・・・・・・・・・・・・・
}
#**************
sub set_logdata_pie{ # 円グラフ用データのセット
・・・・・・・・・・・・・
}
#**************
sub set_logdata{ # 複合棒グラフ用データのセット
・・・・・・・・・・・・・
}
#**************
sub initgd0{ # GDの初期化
・・・・・・・・・・・・・
}
#**************
sub err_wr($){
  # リクエストで不正クエリー文字があった場合呼ばれる。
# テキストエラーイメージ生成

my ($d) = @_;
my $font_file ='/***/fonts/vlgothic/VL-Gothic-Regular.ttf';
$im->stringFT($BaseCref, # 色
$font_file, 10, # フォント・フォントサイズ
0, # 回転角度
5, 15, # X・Y 座標
$d); # 表示文字列
return $im->png;

}

 クラス変数にコピーしたCGI::PSGIオブジェクトのリファレンスを使って、header(PSGI環境変数から取得する為psgi_headerに名称が変更になっています)やparamといったCGI.pmでお馴染みのメソッドを利用しています。
 使ったこと無いのですがWAFを使えば大幅にコードを減らせる気はします。。特にリクエストチェックの部分など。詳しい方からコメントなどいただけたら嬉しいです。
 この記事は3回目でひとまず終了です。