HTTP::Request::AsCGIの使い方
今まで知らなかったんだが、HTTP::Request::AsCGIというのを使うとテストとかにスゴく便利らしい。
というわけで、早速いくつかのブログを見ながら触ってみた。
use strict; use HTTP::Request; use HTTP::Request::AsCGI; use CGI; use Data::Dumper; # HTTP::Requestオブジェクトを作っておく my $url = "http://localhost/test?key1=value1&key2=value2; my $req = HTTP::Request->new("GET", $url); # AsCGIでcgi環境を作る my $c = HTTP::Request::AsCGI->new($req)->setup; my $q = new CGI; # クエリーパラメータを出力してみる for($q->param){ print $_, " => ", $q->param($_), "\n"; }
あれ?なにも表示されないよ??
ちょっと悩んでみたが、sixapartのブログに少し解説があったので読んでみました。
HTTP::Request::AsCGI は STDIN や STDOUT などをテンポラリファイルへのディスクリプタに置き換え、Content-Length があると、STDIN に置き換えられているテンポラリファイルにメッセージボディを書き出しておきます。
あとid:naoyaのブログのコメントの中にもこんなやり取りがありました。
hassylin 2007/01/31 20:08 $cってどこでつかってるんだろ??(初心者)
naoya 2007/01/31 21:51 enviroment and descriptors will automatically be restored when $c is destructed. (via http://search.cpan.org/~chansen/HTTP-Request-AsCGI-0.5/lib/HTTP/Request/AsCGI.pm )
要するに$cが破棄された後でないと標準入出力は普通の状態に戻らないんですね。
ということは上のコードは、AsCGIの処理の部分だけをブロックで囲んでやればよいわけだ。
use strict; use HTTP::Request; use HTTP::Request::AsCGI; use CGI; use Data::Dumper; # HTTP::Requestオブジェクトを作っておく my $url = "http://localhost/test?key1=value1&key2=value2; my $req = HTTP::Request->new("GET", $url); # AsCGIでcgi環境を作る # ここをブロックで囲む my $q; { my $c = HTTP::Request::AsCGI->new($req)->setup; $q = new CGI; } # クエリーパラメータを出力してみる for($q->param){ print $_, " => ", $q->param($_), "\n"; }
こんどはちゃんとパラメータが表示されました。
もうちょっと色々やってみるとこんな感じ。
use strict; use HTTP::Request; use HTTP::Request::AsCGI; use CGI; use Data::Dumper; # HTTP::Requestオブジェクトを作っておく my $url = "http://localhost/test?key1=value1&key2=value2; my $req = HTTP::Request->new("GET", $url); # AsCGIでcgi環境を作る # ここをブロックで囲む my $q; { my $cgi = HTTP::Request::AsCGI->new($req)->setup; # CGI環境に(をエミュレートしたFDに対して)出力する # これはコンソールには表示されない $q = new CGI; print $q->header; print $q->start_html; print $q->h1("テストだよ"); print $q->end_html; # HTTP::Responseのカタチで結果を取得して表示してみる # restore後はコンソールに出力される my $res = $cgi->restore->response; print $res->as_string; } # クエリーパラメータを出力してみる for($q->param){ print $_, " => ", $q->param($_), "\n"; }
ふむ。なるほど。sixapartの中の人を見習って$cを$cgiって書き換えたんだけど、
この方が何してるのかイメージがわくな。
で、結果はこう。
HTTP/1.1 200 OK Date: Sun, 11 May 2008 18:12:18 GMT Content-Length: 369 Content-Type: text/html; charset=ISO-8859-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <h1>テストだよ</h1> </body> </html> key1 => value1 key2 => value2
ふー。直感的にはなんだかよくわからないモジュールだったけど、でもこれはかなり便利。
今後いろいろと使いそうなので、覚えておこう。
あとでちゃんとCPANドキュメントも読んでおかねば。