Ruby Net::HTTP 超时

Posted

技术标签:

【中文标题】Ruby Net::HTTP 超时【英文标题】:Ruby Net::HTTP time out 【发布时间】:2011-01-14 19:28:17 【问题描述】:

我正在尝试编写我的第一个 Ruby 程序,但遇到了问题。该代码必须通过 HTTP 下载 32 个 MP3 文件。它实际上下载了一些,然后超时。

我尝试设置超时时间,但没有任何区别。在 Windows、Cygwin 和 Mac OS X 下运行代码,结果相同。

这是代码:

require 'rubygems'
require 'open-uri'
require 'nokogiri'
require 'set'
require 'net/http'
require 'uri'

 puts "\n Up and running!\n\n"

 links_set = 

 pages = ['http://www.vimeo.com/siai/videos/sort:oldest',
   'http://www.vimeo.com/siai/videos/page:2/sort:oldest',
   'http://www.vimeo.com/siai/videos/page:3/sort:oldest']

 pages.each do |page|
  doc = Nokogiri::html(open(page))
  doc.search('//*[@href]').each do |m|
   video_id = m[:href]
   if video_id.match(/^\/(\d+)$/i)
     links_set[video_id[/\d+/]] = m.children[0].to_s.split(" at ")[0].split(" -- ")[0]
    end
   end
 end

 links = links_set.to_a

 p links

 cookie = ''
 file_name = ''

 open("http://www.tubeminator.com") |f|
   cookie = f.meta['set-cookie'].split(';')[0]
 

 links.each do |link|
  open("http://www.tubeminator.com/ajax.php?function=downloadvideo&url=http%3A%2F%2Fwww.vimeo.com%2F" + link[0],
   "Cookie" => cookie) |f|
      puts f.read
   

  open("http://www.tubeminator.com/ajax.php?function=convertvideo&start=0&duration=1120&size=0&format=mp3&vq=high&aq=high",
   "Cookie" => cookie) |f|
      file_name = f.read
   
  puts file_name

  Net::HTTP.start("www.tubeminator.com")  |http|
   #http.read_timeout = 3600 # 1 hour
     resp = http.get("/download-video-" + file_name)
     open(link[1] + ".mp3", "wb")  |file|
        file.write(resp.body)
     
      
 end 

 puts "\n Yay!!"

这是个例外:

/Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:140:in `rescue in rbuf_fill': Timeout::Error (Timeout::Error)
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:134:in `rbuf_fill'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:116:in `readuntil'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:126:in `readline'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:2138:in `read_status_line'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:2127:in `read_new'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:1120:in `transport_request'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:1106:in `request'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:312:in `block in open_http'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:564:in `start'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:306:in `open_http'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:767:in `buffer_open'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:203:in `block in open_loop'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:201:in `catch'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:201:in `open_loop'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:146:in `open_uri'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:669:in `open'
 from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:33:in `open'
 from test.rb:38:in `block in <main>'
 from test.rb:37:in `each'
 from test.rb:37:in `<main>'

我也很感谢您对其余代码的 cmets。

【问题讨论】:

可能是您在构建视频下载的 url 时出了点问题。选择有问题的网址并尝试手动下载。 嗨 Lucas :) URL 没问题,我可以用浏览器下载文件。问题是在下载较大的文件(大约 20MB)时超时。 【参考方案1】:

对于 Ruby 1.8,我用它来解决我的超时问题。在我的代码中扩展 Net::HTTP 类并使用默认参数重新初始化,包括我自己的 read_timeout 的初始化,我认为应该保持理智。

require 'net/http'

# Lengthen timeout in Net::HTTP
module Net
    class HTTP
        alias old_initialize initialize

        def initialize(*args)
            old_initialize(*args)
            @read_timeout = 5*60     # 5 minutes
        end
    end
end

【讨论】:

谢谢你,在我需要你的那一刻,你就像从天而降的天使。 @Darren 很高兴我能帮上忙 :-) 尼克,您可以将此代码放在应用程序层次结构中的任何位置,只要它保存的文件在运行时加载/需要。 @RansomAni-Gizzle,你为什么这样做而不是像我在这里那样说http = Net::HTTP.new(uri.host, uri.port); http.open_timeout = 5* 60; http.read_timeout = 5* 60 ***.com/questions/14314375/… @Grienders 因为我需要将解决方案模块化并只实例化一次。您的解决方案也可以,但是如果您在另一个文件中使用变量 http 而不使其成为全局变量,则必须重做 "Net::HTTP.new(uri.host, uri.port); http.open_timeout = 5* 60 ; http.read_timeout = 5* 60" 一遍又一遍地在不同的文件中,而你可以把它放在一个重要的地方。我会觉得那很乱……我猜只是个人喜好。 :-)【参考方案2】:

您的超时不在您设置超时的代码中。在这里,你可以使用 open-uri:

open("http://www.tubeminator.com/ajax.php?function=downloadvideo&url=http%3A%2F%2Fwww.vimeo.com%2F" + link[0],

您可以像这样为 open-uri 设置读取超时:

#!/usr/bin/ruby1.9

require 'open-uri'

open('http://***.com', 'r', :read_timeout=>0.01) do |http|
  http.read
end

# => /usr/lib/ruby/1.9.0/net/protocol.rb:135:in `sysread': \
# => execution expired (Timeout::Error)
# => ...
# =>         from /tmp/foo.rb:5:in `<main>'

:read_timeout 是 Ruby 1.9 的新功能(不在 Ruby 1.8 中)。 0 或 nil 表示“没有超时”。

【讨论】:

你知道 Ruby 1.8 的解决方案吗? @madh,我不知道,但可以使用例如 wget。 可以设置Net::HTTP对象的read_timeout和conn_timeout。 替代方案:使用路边。 curb.rubyforge.org API 很奇怪,但它没有任何 Net::HTTP 超时问题(仅适用于 Ruby 1.8.x)。 工作就像一个魅力。感谢您的帮助!

以上是关于Ruby Net::HTTP 超时的主要内容,如果未能解决你的问题,请参考以下文章

关于Go net/http 超时完全指南

net/http:使用 KOPS 的 TLS 握手超时

ruby 超时和系统命令

Ruby 在 n *milli* 秒后超时一段代码

在进行数据库调用的线程中使用 ruby​​ 超时

System.Net.Http.HttpClient 不尊重超时并每次使用默认值