せかいろぐ

ほぼ自分用備忘録

PerlのCPANモジュールHTTP::Cookiesのバグ

PerlでHTTP通信するコードを書いてて気がついたHTTP::Cookiesの挙動不審について。


LWP::UserAgentでCookieを有効にするには以下のようにします。

use LWP::UserAgent;
my $ua = LWP::UserAgent->new(cookie_jar => {});


WWW::Mechanizeでは特に何もしなくてもnewすればCookieが保存・送信されます。

use WWW::Mechanize;
my $mech = WWW::Mechanize->new();


とても便利で簡単なんですが、内部でCookieの処理に使われているHTTP::Cookiesにバグがあるようで、リクエストヘッダにCookieを追加するサブルーチンHTTP::Cookies::add_cookie_headerの動作がちょっとおかしい。

例えばDomain属性が、

domain: .sekai.in;

というCookieがあった時、hoge.sekai.inやabc.sekai.inへはしっかりCookieを送ってくれるんですが、sekai.inへはなぜかCookieを送ってくれない。。。一部サイトでのログイン処理でこれが問題になる場合が。CPANにも数年前に報告されていたけど、また修正されていない様子。

上のリンク先にあるようにHTTP::Cookies.pmのadd_cookie_headerを直接編集するのもアリだけど、複数の環境で動かすときにいちいち直さないとダメで面倒。

ということで、HTTP::Cookies::_hostをオーバーライドして解決。

require HTTP::Cookies;

*HTTP::Cookies::_host = sub {
	my($request, $url) = @_;
	my $h;
	
	if($h = $request->header("Host")){
		$h =~ s/:\d+$//;
	}else{
		$h = $url->host;
	}
	
	#add_cookie_headerから呼ばれた時、頭にドットを付加
	my @calr = caller(1);
	if($calr[3] =~ /add_cookie_header/){
		$h =~ s/(^[^\.])/\.\1/;
	}
	
	return lc($h);
};