CatalystでPOSTの生データを取得する

ハマッたのでメモ。

以前どこかでPOSTの生データを取得するには$c->req->bodyから取れるというのをうろ覚えしてたのでやってみたんだけど取れなかった。

ちゃーんとPOSTでリクエストしているのに取れないわけだ。

ちなみにコードは以下。

use LWP::UserAgent;

my $url          = 'http://example.com/hoge';
my $query_string = "foobarbaz";

my $ua  = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => $url);
$req->content_type('application/x-www-form-urlencoded');
$req->content($query_string);

my $res = $ua->request($req);

こーんな感じでリクエストしてたんですね。

なんでか全然わかんなかったので、ためしに単なるCGI用意してSTDINからreadでPOST生データを取得しみたところちゃんと取れた。だからリクエストに問題はないだろう、・・・・・そう思っていた時期が俺にもありました・・・・。




・・・・でまぁこんな場合我が家の家訓に則って「ソース嫁」ってことで。

でどうやらCatalystではHTTP::Bodyというのを使ってクエリの解析を行っていることがわかった。

でそのHTTP::Bodyの実装を見ると、リクエストのコンテントタイプをみて厳密に処理分けを行っているのがわかった。

なるほどなるほど、application/x-www-form-urlencodedでリクエストするとHTTP::Body::UrlEncodedが読み込まれ、クエリの解析を行うので生データは保持しない。

だから$c->req->bodyでPOSTの生データを取れなかったのだ。

CatalystでPOSTの生データを取りたければ、リクエスト時のコンテントタイプをapplication/octet-streamにしなければならない。

application/octet-streamにすれば、HTTP::Body::OctetStreamが読み込まれ、生データを得ることができる。

なんだか面倒。HTTP::Body便利だけど厳密すぎるなぁ、両方取りたい時どうすりゃいいのら?ってか僕が壮大な勘違いをしているのかもしれない。もっと別の方法があるのかも。




どーでもいいけど問題の切り分けをミスると変に時間使っちゃうよなぁ。始めにリクエストには問題ないと決め付けてしまったせいで問題解決に凄い時間がかかった。反省。