dreamedge.net

HTTP接続のタイムアウト設定

2009-08-26T21:36:00+0000

rubyのhttp通信は,60秒でタイムアウトするように設定されている.通常はそれで問題ないのだけど,自前のスクリプトとかで時間のかかるモノを動かす場合に困る.

このタイムアウト時間はNet::HTTPのinitializeプロセスで60秒に設定されて,その後read_timeoutメソッドで変更可能になっている.
net/http.rb(Debian系なら/usr/lib/ruby/1.8/net/http.rb)を見ると下のような感じに書かれている.

    # Creates a new Net::HTTP object for the specified +address+.
    # This method does not open the TCP connection.
    def initialize(address, port = nil)
      @address = address
      @port    = (port || HTTP.default_port)
      @curr_http_version = HTTPVersion
      @seems_1_0_server = false
      @close_on_empty_response = false
      @socket  = nil
      @started = false
      @open_timeout = nil
      @read_timeout = 60
      @debug_output = nil
      @use_ssl = false
      @ssl_context = nil
    end
---中略---
    # Seconds to wait until reading one block (by one read(2) call).
    # If the HTTP object cannot open a connection in this many seconds,
    # it raises a TimeoutError exception.
    attr_reader :read_timeout

    # Setter for the read_timeout attribute.
    def read_timeout=(sec)
      @socket.read_timeout = sec if @socket
      @read_timeout = sec
    end

この実装自体は自然なんだけれど,open-uriとかのラッピングされた状態で扱う場合にタイムアウトの変更ができなくて困る.どうしたらいいかと情報を探していたら,Net::HTTPを上書きしちゃう方法が照会されていた.

class Net::HTTP
  def initialize_new(address, port = nil)
    initialize_old(address, port)
    @read_timeout = 120
  end
  alias :initialize_old :initialize
  alias :initialize :initialize_new
end

かなり力ずくだけど確かに有効.