LWP::UserAgentで基本認証とPOSTを

LWP::UserAgentでBASIC認証つきでリクエストする - bits and bytes という記事で、LWP::UserAgentを用いて基本認証が必要なページにアクセスする方法について述べられているのですが、以下の点について不思議に思っていました。(その時のブックマーク)

が、後日記事を読み直したところ補足で以下のように追記されていました。

ご指摘いただいた通りrealmなんて普段作る側としても意識していないしめんどくさいだけなので、自分も本当は $req->authorization_basic したかったのですが、はじめに白状したとおり LWP::UserAgent::post とか HTTP::Request::Common::POST とか HTTP::Request::new の引数の POST => とかもろもろ理解していなかったため、たたみラボさんの記事をまねしつつ書いてみたけどPOSTにパラメータをどうやったら渡せるかわかんない!という状態であきらめたというのが真相です....

※註 「たたみラボさんの記事」: LWP::UserAgentでBasic認証サイトにアクセスする方法|blog|たたみラボ

それで先に挙げた2点についても納得できました。ただそういうことであれば、以下のようにしてごく簡単に実現できます。

  1. HTTP::Request::Common のPOSTメソッドで、パラメタを渡したPOST requestオブジェクトを作成。
  2. そのrequestオブジェクトに対し、authorization_basicにより認証情報を追加。
  3. そのようにして作ったrequestオブジェクトをLWP::UserAgentのrequestメソッドに渡す。

以下に簡単な例を。

use strict;
use HTTP::Request::Common;
use LWP::UserAgent;

# requestオブジェクトを作成
my $req = POST( 'http://localhost/debug.cgi', [foo => 'aaa', bar => 'bbb'] );
$req->authorization_basic('user1', 'pass1');

print "========== REQUEST ==========\n";
print $req->as_string;

# resposeオブジェクトを取得
my $ua = LWP::UserAgent->new;
my $res = $ua->request($req);

print "========== RESPONSE =========\n";
print $res->as_string;

debug.cgiはこんな感じで。

#!/usr/bin/perl
use strict;
use CGI qw(:cgi);
print header('text/plain');
foreach (param) {
  print $_, '=', param($_), "\n";
}

実行結果はこのようになります。

$ perl post.pl
========== REQUEST ==========
POST http://localhost/debug.cgi
Authorization: Basic dXNlcjE6cGFzczE=
Content-Length: 15
Content-Type: application/x-www-form-urlencoded

foo=aaa&bar=bbb
========== RESPONSE =========
HTTP/1.1 200 OK
Connection: close
Date: Mon, 11 Jun 2007 07:19:27 GMT
Server: Apache/1.3.33 (Cygwin)
Content-Type: text/plain; charset=ISO-8859-1
Client-Date: Mon, 11 Jun 2007 07:19:27 GMT
Client-Peer: 127.0.0.1:80
Client-Response-Num: 1
Client-Transfer-Encoding: chunked

foo=aaa
bar=bbb
$

リクエストヘッダにAuthorizationヘッダが追加され、debug.cgiはPOSTパラメタを受け取っていることが確認できるかと思います。