Hatena::ブログ(Diary)

naoyaのはてなダイアリー

November 16, 2005

CGI.pm の POSTDATA

CGI.pmでtext/xmlなPOSTデータを読みたい場合、

my $q = CGI->new;
$q->param('POSTDATA')

で読める。いままで知りませんでした。

blog.nomadscafe.jp: CGI.pmでtext/xmlなPOSTデータを読みたい場合

CGI.pm で $q->param('POSTDATA') とすると、POST で送られて来たデータの body をそのまま取り出せる、という話。

どういうときにこの API が役に立つかというと、かぜぶろさんのタイトルにある通り XML な API をサーバー側に実装したいとき。

もともと CGI.pm は通常のウェブリクエストを処理するために考えられているので、POST のデータを標準入力から読み込み、それを parse して $q->param('foobar') と GET のときと同じ API でアクセスできるようにしてます。が、AtomPP や XML-RPC なんかの場合、その POST のデータが name=value&name=value... ではなく XML になってるので、CGI.pm の parse ロジックをすっとばしてそのままごっそり持ってくる必要が出てきます。で、POSTDATA でそれを取得すると。

ただ、CGI.pm のソースを読むと分かるとおり POSTDATA で生データがとれるケースというのは結構限定的で、Request Method が POST 且つ Content-Type がフォームから送られてきてる以外のとき、となってます。そうすると、XML-RPC のときとかはいいけど、PUT を使う AtomPP を実装するときに困ったりします。AtomPP の PUT は CRUD の U (Update) に対応するので、POST の時同様クライアントからデータをもらわないといけない、でも CGI.pm の API ではそれがとれない、という罠があります。

結局、

## CGI の POSTDATA は PUT では使えないので直接読む
my $len = $ENV{CONTENT_LENGTH} || 0;
read STDIN, $self->{request_content}, $len;
unless ($self->{request_content}) {
    return $self->error(500, 'Atom feed body is required.');
}
1;

みたいなことをやるはめになってしまいます。CGI.pm の POSTDATA がある周辺がメソッドになってれば、それをオーバーライドするなりっていう方法があると思うんですが。

ちょっと話がずれるのですが、先日の Web API とフレームワークのところも絡めると、Web API が簡単にハンドリングできるフレームワークは、リクエストがどんな形をしているかを断定的に実装してはいけない気がします。

つまりは、CGI.pm のようなものと密結合するのはなく、フレームワーク独自の Request クラスを作って、それが CGI.pm や Apache::Request などのラッパになっていると。そのラッパが、実際に利用するリクエストクラスをいじってもう少し細かい API を持っているような感じ。

Catalyst は Catalyst::Request でその抽象化をしていて、$c->req->body で生データが取り出せるようになってますね。Catalyst::Request のインスタンスは各エンジンの初期化処理の中で prepqre_request により組み立てられます。Builder パターンみたいな具合。mod_perl とか server.pl とか FastCGI とか、動作環境によってリクエストの実装が変わってくるのを想定してこういう作りになってるんだと思いますが、結果として Catalyst::Request を賢くすれば、Web API を実装するときに必要な API をフレームワークが用意することができて幸せです。

Sledge とか Rails もこんな感じでリクエストが抽象化されてますよね、確か。

tokuhiromtokuhirom 2005/11/17 10:39 Sledge の場合、CGI.pm は Apache::Request 風にラッピングしてます。が、Apache::Request は直接イジります。

naoyanaoya 2005/11/17 11:16 らしいすね。ikebeさんがそこがイケテナスとコメントしてた。w

NathanNathan 2006/05/11 06:26 Good design!
[url=http://ktzxvlsx.com/xahp/grke.html]My homepage[/url] | [url=http://bhspmmye.com/vxtx/gxvr.html]Cool site[/url]

RexRex 2006/05/11 06:26 Well done!
<a href=”http://ktzxvlsx.com/xahp/grke.html”>My homepage</a> | <a href=”http://iljrqwke.com/nulx/cyex.html”>Please visit</a>

BruceBruce 2006/05/11 06:26 Nice site!
http://ktzxvlsx.com/xahp/grke.html | http://moaxwqsu.com/pwpl/tdzi.html

VickyVicky 2006/05/13 03:22 Great work!
[url=http://rkskkfij.com/tqkz/mcbs.html]My homepage[/url] | [url=http://ohbeqpda.com/crko/yaat.html]Cool site[/url]

GinaGina 2006/05/13 03:23 Thank you!
<a href=”http://rkskkfij.com/tqkz/mcbs.html”>My homepage</a> | <a href=”http://jaacumol.com/llsj/rdre.html”>Please visit</a>

PhillipPhillip 2006/05/13 03:23 Well done!
http://rkskkfij.com/tqkz/mcbs.html | http://nqguglsg.com/npxx/irha.html

mary stantonmary stanton 2007/02/05 06:38 These several circumstances contributed to render the warfare more vindictive than ever. http://www.xvyn.com/66/mary-stanton.html <a href=”http://www.xvyn.com/66/mary-stanton.html”>mary stanton</a> [url]http://www.xvyn.com/66/mary-stanton.html[/url]

トラックバック - http://d.hatena.ne.jp/naoya/20051116/1132106196