2007年6月29日金曜日

CGIの進化(2)

初期のCGIではページごとにCGIを開発していた。小規模アプリケーションではそれでもよいが、大規模アプリケーションでは通用しない。ファイルが多くなり、維持管理が困難となる。そこで複数のCGIを1つにまとめる技法が必要となった。
パラメータで判断する方法もあるが、その方法ではいつもフォームを使わなければならない。そこで、一般的にはPATH_INFOを用いることが多い。
PATH_INFOとはURLのCGI以下のパスである。例えば、foo.cgi/barというURLがあると/barがPATH_INFOである。このbarと同じ名前の関数を呼び出せば(1つのアプリケーションの)複数のプログラムを1つのCGIに同居させることができる。この技法はCGI::Applicationでも使われている。
以下に例を示す。

#!c:/xampp/perl/bin/perl -w
##!!
use strict; # 安全のための制限を課す
use warnings; # 警告を出す(same as -w)
use utf8; # UTF-8で書いている
use CGI; # CGIである。
binmode STDOUT,":utf8"; # 標準出力はUTF8
my $encoding = 'utf8'; # HTMLの文字コード
my $lang = 'ja'; # 言語は日本語

my $q = CGI->new();
dispatch();
exit 0;

# foo.cgi/bar.doなら関数barを呼び出す
sub dispatch {
my $path_info = $q->path_info();
my $action = "do_index"; # 省略時のアクション
if ($path_info =~ /\/([^\/\.]*)\.do/) { # .doはアクションを区別する拡張子
$action = "do_$1"; # アクションは接頭語do_から始まる
}
eval {
no strict 'refs'; # ここだけ参照の制限を緩める
&{$action}(); # 関数を呼び出す
};
do_nothing($action) if $@; # 関数がない場合
}

sub do_nothing {
my ($action) = @_;
response("no such an action $action");
}

sub do_index {
my $url = $q->url();
response(<<HTML);
<p><a href="$url/english.do">English</a></p>
<p><a href="$url/japanese.do">Japanese</a></p>
HTML
}

sub do_english {
response("Hello");
}

sub do_japanese {
response("こんにちは");
}

sub response {
my ($body) = @_;
print $q->header(-type=>'text/html',-charset=>$encoding);
print $q->start_html(-title=>'Hello Perl',-lang=>$lang,-encoding=>$encoding);
print $body;
print $q->end_html();
}

0 件のコメント: