Mechanize2.0 ではまる

Mechanizeをver1からver2に上げたら、社内で使っていたスクリプトが動かなくなった。ログオン部分で引っかかり先に進めない。とりあえず、バージョン指定で旧バージョンを指定してしのいでいたのだが、「そんなに難しいことは無いだろう」と調べてみた。


定番のid:kitamomongaさんの情報サイト、http://d.hatena.ne.jp/kitamomonga/20110628/ruby_mechanize_2_0 を見るが、どうも該当しそうな記述が無い。ログをとってみると、シングルサインオン認証済キーのCookieを送っていない。関連の部分を調べてみると、あった。
Cookieを追加する Mechanize::CookieJar#add の冒頭が変更されている。

     return unless valid_cookie_for_uri?(uri, cookie)

valid_cookie_for_uri?は、こういうチェックをしているが、この2つめがver1ではやってない。

     # Permitted:     A Set-Cookie for x.foo.com for Domain=.foo.com
     # Not Permitted: A Set-Cookie for y.x.foo.com for Domain=.foo.com because
     #                y.x contains a dot
     # Not Permitted: A Set-Cookie for foo.com for Domain=.bar.com


シングルサインオン認証のCookieは、domain=.example.com と広めに投げられているが、使いたいホスト名は、foo.intra.example.com だ! domain=.intra.example.com だったのなら問題なかったのだけど。
不許可の理由は、共用レンタルサーバーの絡みかと思ったけど、関係ないか。example.sakura.ne.jp とかから、domain=.sakura.ne.jp で投げ放題だよね。
「できるだけ狭い範囲に投げろ」という精神論か?それはサイトに言ってくれよ〜。クライアント側ではブラウザ互換にしてほしいな。


対応としては、Mechanize::CookieJar#add の上書き修正。add を呼ぶ前に domain= を書き換える手もあるか。

class Mechanize::CookieJar
  def add(uri, cookie)
    return unless uri.host =~ /#{self.class.strip_port(cookie.domain)}$/i
    normal_domain = cookie.domain.downcase
    @jar[normal_domain] ||= {} unless @jar.has_key?(normal_domain)
    @jar[normal_domain][cookie.path] ||= {}
    @jar[normal_domain][cookie.path][cookie.name] = cookie
    cookie
  end
end