Alexandre Alexandre - 1 month ago 13
Ruby Question

How to cancel Ruby Net::HTTP request?

How do I get Ruby's Net::HTTP module to cancel a request?

The call to

http.finish
below raises an error. I get the impression that the response object doesn't know that the connection was closed and still expects more data.

I want to avoid making a HEAD request. So, make a GET request, unless content-type is HTML, cancel the request.

Net::HTTP.start(uri.host, uri.port) do |http|
http.request_get(uri.path) do |response|
unless response['content-type'] =~ /html/i
http.finish
end
end
end

/usr/lib/ruby/1.8/net/http.rb:2241:in `stream_check': attempt to read body out of block (IOError)
from /usr/lib/ruby/1.8/net/http.rb:2171:in `read_body'
from /usr/lib/ruby/1.8/net/http.rb:2198:in `body'
from /usr/lib/ruby/1.8/net/http.rb:2137:in `reading_body'
from /usr/lib/ruby/1.8/net/http.rb:1052:in `request'
from /usr/lib/ruby/1.8/net/http.rb:948:in `request_get'
from net.rb:9
from /usr/lib/ruby/1.8/net/http.rb:543:in `start'
from /usr/lib/ruby/1.8/net/http.rb:440:in `start'
from net.rb:7

Answer

I ended using this solution (catching the exception):

require 'net/http'


uri = URI.parse('http://mirror.globo.com/ubuntu/releases/6.06.2/ubuntu-6.06.2-server-amd64.iso')

begin
  Net::HTTP.start(uri.host, uri.port) do |http|
    http.request_get(uri.path) do |response|
      unless response['content-type'] =~ /html/i
        p response['content-type']
        p 'didnt get html, stopping transfer'
        http.finish      
        # break
      end
      response.read_body do |data|
        p 'receiving data'
      end
    end
    p 'transfer succesful!'
  end
rescue 
  p 'rescued it'
end

p 'broke out of net loop'

I also had a look at libcurl through curb (http://curb.rubyforge.org) but it relies on callbacks, not blocks, and the callbacks don't pass in the Curl instance so there's no way to kill the connection like there is with Net::HTTP.