読者です 読者をやめる 読者になる 読者になる

commandlinefuの APIアクセスに Furlが使えない理由を考える

perl furl

HTTPの知識が皆無なのでなんとも言えないのですが、
気になったなのでに調べてみた。きっと送るヘッダが違うんだろうと
いうことで、それについて調べてみます。

#!/usr/bin/env perl
use strict;
use warnings;
use lib qw(../lib);
use Furl;

my $url = 'http://www.commandlinefu.com/commands/matching/ssh/c3No/json';

my $ua_furl = Furl->new();

my $res_furl = $ua_furl->get($url);
unless ($res_furl->is_success) {
    die "Error : ", $res_furl->status_line, "\n";
}

print "[Furl]\n", $res_furl->headers->as_string, "\n";

こんなコードを走らせたときに、Furlがどんなヘッダを送っているかを、
ソースコードに手を入れて調べてみた。そしたら以下のようなものがでた。

GET /commands/matching/ssh/c3No/json HTTP/1.1
Host: www.commandlinefu.com:80
Connection: keep-alive
User-Agent: Furl::HTTP/0.21

素人目には普通にしか見えないんですが、きっと何かが違うんでしょう。


一方 curlはどんなヘッダを送っているかを調べてみた。curlは -vオプションを
つけて起動すると、send headerが見れます。結果は以下のようになりました。

  % curl http://www.commandlinefu.com/commands/matching/ssh/c3No/json
  GET /commands/matching/ssh/c3No/json HTTP/1.1
  User-Agent: curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zl
  ib/1.2.3.4 libidn/1.18
  Host: www.commandlinefu.com
  Accept: */*

なるほど、Acceptかって思ったんですが、違ってました。となると違いは
ってなったときに、Furlは Hostの後ろにポート番号が指定されています。
んなわけね〜だろって思ったんですが、これを取り除くコードを実行して
みたところ、ちゃんと動きました。それぞれの結果を示します。
共にソースに手を入れて、ヘッダを強引に表示させてます。


ポート番号あり版

GET /commands/matching/ssh/c3No/json HTTP/1.1
Host: www.commandlinefu.com:80
Connection: keep-alive
User-Agent: Furl::HTTP/0.21

[Furl]
connection: Keep-Alive
set-cookie: PHPSESSID=9dbc74092d0198d2fa0e69f6eda24571; expires=Tue, 25-Jan-2011 13:28:53 GMT; path=/
cache-control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
keep-alive: timeout=15, max=100
date: Mon, 24 Jan 2011 13:58:53 GMT
vary: Accept-Encoding
content-length: 3052
pragma: no-cache
content-type: text/html
server: Apache/2.2.12 (Ubuntu)
expires: Thu, 19 Nov 1981 08:52:00 GMT

ポート番号なし版

GET /commands/matching/ssh/c3No/json HTTP/1.1
Host: www.commandlinefu.com
Connection: keep-alive
User-Agent: Furl::HTTP/0.21

[Furl]
connection: Keep-Alive
set-cookie: PHPSESSID=ecdfd25f45bed5b4f9ad7081249e490b; expires=Tue, 25-Jan-2011 13:30:36 GMT; path=/
set-cookie: ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%227b31564679ca2b50aafed0dccbfd8f05%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A14%3A%22175.184.65.155%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A15%3A%22Furl%3A%3AHTTP%2F0.21%22%3Bs%3A13%3A%22last_activity%22%3Bs%3A10%3A%221295877636%22%3B%7D5b0d74b656c2669106dfeeaff96d9226; expires=Tue, 25-Jan-2011 14:00:36 GMT; path=/
cache-control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
keep-alive: timeout=15, max=100
date: Mon, 24 Jan 2011 14:00:36 GMT
vary: Accept-Encoding
content-length: 7019
pragma: no-cache
content-type: application/json
server: Apache/2.2.12 (Ubuntu)
expires: Thu, 19 Nov 1981 08:52:00 GMT

ちゃんと JSONが返ってきてます。
これで原因がわかりました。

まとめ

違いはポート番号を Hostヘッダにつけるかつけないかということだった
ようです。studyinghttp.net - を見ると、
HOSTにポート番号は指定していいみたいなんで、サーバ側に問題があると
いうことでいいんでしょうか?

追記

Furl-0.22でこの問題に対応したようです。
アップデートしましょう。