首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何取消Ruby Net::HTTP请求?

如何取消Ruby Net::HTTP请求?
EN

Stack Overflow用户
提问于 2010-02-02 05:22:02
回答 3查看 3.2K关注 0票数 2

如何让Ruby的Net::HTTP模块取消请求?

下面对http.finish的调用引发了一个错误。我的印象是,response对象不知道连接已关闭,仍然需要更多数据。

我想避免发出HEAD请求。因此,发出一个GET请求,除非content-type是HTML,否则取消该请求。

代码语言:javascript
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-04 01:57:28

我结束了使用这个解决方案(捕捉异常):

代码语言:javascript
复制
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那样终止连接。

票数 -1
EN

Stack Overflow用户

发布于 2010-02-02 05:40:34

重新编辑,原始答案在底部

我不认为你在你的pastie的第一个代码片段中无所事事。尝试执行以下操作,了解我的意思:

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2010-02-02 07:20:59

我没有通过本地代理来确保这一点,但是速度告诉我,除非它的content-type是HTML,否则它不会读取正文。

代码语言:javascript
复制
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
    }
  }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2180183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档