PerlでHTTPレスポンスヘッダを取得

まだLWP::UserAgentをいじっているのだが、レスポンスヘッダ周りの操作でちょっと迷ってしまった。

レスポンスヘッダを文字列として取得する

これは、HTTP::Requestのheaders_as_stringメソッドを使えば良い。

#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => 'http://www.example.com/');
my $res = $ua->simple_request($req);

print $res->headers_as_string;

ちなみに最後の行は、以下のように書くこともできる。

print $res->headers->as_string;

見た目そっくりなのだが、何が違うかと言うと。$res->headers_as_string の方は、HTTP::Requestで定義されている "headers_as_string"メソッドを使っている。一方、$res->headers->as_stringの方は、HTTP::Headersオブジェクトのas_stringメソッドを使っている。

両者は何が違うかと言うと……得られる結果は何も違わない。HTTP::Messageのperldocには、

$mess−>headers_as_string:

This will be the same as $mess−>headers−>as_string, but it will make your program a whole character shorter :−)

と書いているが、見て分かる通り、1文字減るだけである :-)

レスポンスヘッダのヘッダ名と値をそれぞれ取得する

先ほどはas_stringでごちゃっとした文字列として取得したので、今度はヘッダごとにフィールド名と値で分けて取得することを考える。

これには、HTTP::Headersオブジェクトのheader_field_namesメソッドを使えば良い。これでヘッダ名のリストが返るので、HTTP::Headersオブジェクトのheaderメソッドでそれぞれの値を取り出せば良いのだ。

#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => 'http://www.example.com/');
my $res = $ua->simple_request($req);

my @header_names = $res->headers->header_field_names;
foreach my $header_name (@header_names) {
  print $header_name . ": " . $res->headers->header($header_name) . "\n";
}

なんだか見た目が若干ややこしいので、少し丁寧に解説する。

my @header_names = $res->headers->header_field_names;

というのは、perldoc HTTP::Requestすれば分かるけど、 [$res->headers]でHTTP::Headerオブジェクトを取得している。そしてperldoc HTTP::Headerを見れば書かれている、HTTP::Headerオブジェクトのheader_field_namesメソッドを実行している。これにより、このHTTPレスポンスヘッダに書かれているフィールド名を配列として取得できる。

続いて、この配列から一つずつフィールド名を取り出して値を表示する。

  print $header_name . ": " . $res->headers->header($header_name) . "\n";

この、[$res->headers->header($header_name)]というのが猛烈にややこしそうだが……先ほどと同様、[$res->headers]はHTTP::Headerオブジェクトを取得し、そのheaderメソッドで該当フィールドの値を取得しているだけ。

これで、フィールド名と値をコロンで連結してprintすれば、as_stringと同じものが得られる。