From: Daniel DeLorme Date: 2010-05-15T11:19:34+09:00 Subject: Re: Asynchronous HTTP request Brian Candler wrote: > Hmm. Well you can delay reading the body like this: > > http = Net::HTTP.start(...) > res = http.get(...) > ... do some stuff > answer = res.read_body > > but it'll wait for the response headers before get() returns. So, you > should just pick the bits you need out of /usr/lib/ruby/1.8/net/http.rb > directly. Thanks for your answer. It was a bit more low-level than I would've liked to, but it helped me get the creative juices flowing. In the end my solution involved wrapping the request's socket in a Fiber. Quite a monkeypatch perhaps, but it seems to work: class ASync class ASocket < BasicObject def initialize(socket) @socket = socket end def method_missing(name, *args, &block) ::Fiber.yield if name =~ /read/ @socket.send(name, *args, &block) end end def initialize(uri, headers={}) uri = URI.parse(uri) unless uri.is_a?(URI) @fiber = ::Fiber.new do Net::HTTP.start(uri.host, uri.port) do |http| http.instance_eval{ @socket = ASocket.new(@socket) } @response = http.get(uri.request_uri, headers) end end @fiber.resume #send the request end def method_missing(*args, &block) @fiber.resume until @response @response.send(*args, &block) end end