如何让Ruby的Net::HTTP模块取消请求?
下面对http.finish的调用引发了一个错误。我的印象是,response对象不知道连接已关闭,仍然需要更多数据。
我想避免发出HEAD请求。因此,发出一个GET请求,除非content-type是HTML,否则取消该请求。
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发布于 2010-02-04 01:57:28
我结束了使用这个解决方案(捕捉异常):
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'我还查看了libcurl through had (http://curb.rubyforge.org),但它依赖于回调,而不是块,而且回调不会传入Curl实例,因此无法像Net::HTTP那样终止连接。
发布于 2010-02-02 05:40:34
重新编辑,原始答案在底部
我不认为你在你的pastie的第一个代码片段中无所事事。尝试执行以下操作,了解我的意思:
h = Net::HTTP.new uri.host,uri.port
h.set_debug_output $stderr
h.start do |http|
http.request_get(uri.path) do |response|
end
end实际情况是,通过发出GET,您的客户端有义务从套接字读取整个文档,而不管您是否实际对其执行任何操作。这只是HTTP规范的一部分。
如果不调用response.read_body,就会阻止代码将响应读取到memory中,但是直到所有数据都从套接字中读出之后,该块才会返回。即使您决定不将响应读入内存,您的break调用的阻塞也会在最终的read之前中断,这是为了使您的代码符合HTTP。I edited your pastie来指出最终读取发生的位置。
你只是碰巧正在读取一个巨大的ISO文件,所以看起来你就像是在闲置。
简而言之,如果您不打算读取整个文档,那么应该发出一个HEAD请求,正如HTTP规范中所指定的那样。
复杂的答案是,如果你发出一个字节范围作为指定的GET,你可以发出一个部分here,但是我不确定ruby http客户端库是否支持这种操作模式。
通过调用http.finish,您可以提前关闭tcp套接字,它完成了将您从代码块中分离出来的工作,但在调用代码时会引发异常,因为您“不应该”这样做。如果您愿意捕获异常,欢迎您调用finish,但是您并没有很好地使用HTTP。
原始答案
您不应该调用finish,当块退出时,连接将关闭。文档here。
异常是从this code引发的
如果您真的想强制套接字提前关闭,只需捕获IOError即可。
我刚刚注意到,您正在将response初始化为调用head的结果,但随后您再次将其用作块参数。只需在调用request_get之前检查内容类型,条件是content_type。
发布于 2010-02-02 07:20:59
我没有通过本地代理来确保这一点,但是速度告诉我,除非它的content-type是HTML,否则它不会读取正文。
url = URI.parse('http://alicebobandmallory.com/')
body=""
res = Net::HTTP.start(url.host, url.port) {|http|
http.request_get(url.path) {|response|
break unless response['content-type'] =~ /html/i
response.read_body {|b|
body<<b
}
}
}https://stackoverflow.com/questions/2180183
复制相似问题