Walrus,Digit. | 一覧 | 検索 | 更新履歴(RSS) | 新規作成
はてなブックマークに追加 はてなブックマークを表示 編集 | 編集(管理者用) | 差分

Perlモジュール/HTTP::Lite

編集

LWPの簡易版として使えるPerlモジュール。

インストールはPPMまたはCPANモジュールで。 インストールはせず、モジュールだけを取得する場合にはCpanModule:HTTP::Liteからどうぞ。

HTTP::Liteのドキュメント。

編集

HTTP::Liteモジュール 2.1.1版、2.1.4版中のPOD文書を訳したものが以下です。

Perldoc.jp上で、2.1.1版、2.1.4版のものをHTML形式で読むことができます。

perldoc.jpへの登録は(CVSの使い方を知らないので)perldoc.jpの岩井さんにお願いしました。 ありがとうございました。

HTTP::Liteを使う。

シノプシスより。

use HTTP::Lite;
$http = new HTTP::Lite;
$req = $http->request("http://www.cpan.org/") 
	or die "Unable to get document: $!";
print $http->body();

HEADコマンドの実行。

HTTPヘッダーのみを取得するHEADコマンドは更新確認などに良く用いられますが、HTTP::Liteにこれを行うためのメソッドはないようです。 そこで乱暴ですが、$http->{'method'}を直接指定することでHEADを実行することができます。

use HTTP::Lite;
$http = new HTTP::Lite;
$http->{'method'} = 'HEAD';
$req = $http->request("http://www.cpan.org/") 
	or die "Unable to get document: $!";
print $http->body();

2.1.4版ではメソッドを明示的に指定できるようになったようです。 この項はいずれ改稿します。

プロキシ対応、HEADも可能なPerlスクリプト。

HTTP::Liteモジュールを使った簡単なHTTPクライアントスクリプトの例です。 引数の展開や実行結果の出力が大部分を占めており、実際の処理はとても簡単です。

use HTTP::Lite;

my $method = 'GET';
my $url    = '';
my $proxy  = '';

&initialize;
&main;

sub initialize {
	foreach (@ARGV) {
		if ($_ =~ /^-(head|get)$/i) {
			$method = $1;
		} elsif ($_ =~ /^-proxy$/i) {
			$proxy = shift(@ARGV);
		} elsif ($_ =~ /^http:\/\//) {
			$url = $_;
		}
	}
	exit unless ($url);
	$method = uc($method);
	$method = 'GET' unless ($method eq 'HEAD' or $method eq 'GET');
}

sub main {
	my $http = new HTTP::Lite;
	$http->{'method'} = $method;
	$http->proxy($proxy) if $proxy;
	my $req = $http->request($url) or die "Unable to get document: $!";
	print join("\n", $http->headers_array(), '', $http->body(), '');
	return;
}

このファイルを「pget.pl」などのファイル名で保存し、以下のように使用できます。

perl pget.pl [-head|-get] [-proxy PROXY_URL] URL

LWP::Simpleライクなmirrorサブルーチン。

LWP::Simpleの持つmirrorサブルーチン同様に、ローカルファイルとURLの更新日時を比較して新しければダウンロードするサブルーチンをHTTP::Liteで実装します。 実際にはLWP::Simpleのmirrorサブルーチンはこの他に、ファイル保存後に'Content-length'とファイルサイズの比較を行っていますが、ここではそこまでは行いません。

sub mirror {
	my $url  = shift;
	my $file = shift;
	return undef unless ($url and $file);
	# make value of 'If-Modified-Since'
	my $modified = undef;
	if (-e $file) {
		my @days_of_week    = qw(Sun Mon Tue Wed Thu Fri Sat);
		my @monthes_of_year = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
		my $time  = (stat($file))[9];
		my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($time);
		$modified = sprintf(
			"%s, %02d %s %04d %02d:%02d:%02d GMT",
			$days_of_week[$wday], $mday, $monthes_of_year[$mon], $year+1900,
			$hour, $min, $sec
		);
	}
	# process fetch
	my $http = new HTTP::Lite;
	$http->add_req_header('If-Modified-Since', $modified) if ($modified);
	my $req = $http->request($url) or die "Unable to get document: $!";
	print "result : $req\n";
	if ($req == 200) {
		open(OUT, ">$file");
		print OUT $http->body();
		close OUT;
	}
}

取得するURLが'http://www.cpan.org/'、ローカルの保存ファイル名が'index.html'であれば、次のようにして使います。

&mirror('http://www.cpan.org/', 'index.html');

実行時にresultが表示されますが、200であれば取得成功、304であればローカルファイルの方が新しかったので、更新しなかったことを示します。


2.1.4版のHTTP::Liteモジュールにはリクエストヘッダの各項目名を小文字にして送ってしまうというバグがあり、If-Modified-Sinceが期待通りに働きません。 2.1.6版ではこのバグが改修されています。

コメント

訳の誤りのご指摘等も歓迎。

[[#rcomment]]