как протестировать URL-адрес open-uri перед обработкой любых данных - PullRequest
9 голосов
/ 24 августа 2011

Я пытаюсь обработать контент из списка ссылок, используя "open-uri" в ruby ​​(1.8.6), но плохо получается, когда я получаю сообщение об ошибке, когда одна ссылка не работает или требует аутентификации:

open-uri.rb:277:in `open_http': 404 Not Found (OpenURI::HTTPError)
from C:/tools/Ruby/lib/ruby/1.8/open-uri.rb:616:in `buffer_open'
from C:/tools/Ruby/lib/ruby/1.8/open-uri.rb:164:in `open_loop'
from C:/tools/Ruby/lib/ruby/1.8/open-uri.rb:162:in `catch' 

или

C:/tools/Ruby/lib/ruby/1.8/net/http.rb:560:in `initialize': getaddrinfo: no address associated with hostname. (SocketError)
from C:/tools/Ruby/lib/ruby/1.8/net/http.rb:560:in `open'
from C:/tools/Ruby/lib/ruby/1.8/net/http.rb:560:in `connect'
from C:/tools/Ruby/lib/ruby/1.8/timeout.rb:53:in `timeout'

или

C:/tools/Ruby/lib/ruby/1.8/net/protocol.rb:133:in `sysread': An existing connection was forcibly closed by the remote host. (Errno::ECONNRESET)
from C:/tools/Ruby/lib/ruby/1.8/net/protocol.rb:133:in `rbuf_fill'
from C:/tools/Ruby/lib/ruby/1.8/timeout.rb:62:in `timeout'
from C:/tools/Ruby/lib/ruby/1.8/timeout.rb:93:in `timeout'

есть ли способ проверить ответ (URL) перед обработкой каких-либо данных?

код:

require 'open-uri'

smth.css.each do |item| 
 open('item[:name]', 'wb') do |file|
   file << open('item[:href]').read
 end
end

Большое спасибо

Ответы [ 2 ]

23 голосов
/ 24 августа 2011

Вы можете попробовать что-то вроде

    require 'open-uri'

    smth.css.each do |item|
     begin 
       open('item[:name]', 'wb') do |file|
         file << open('item[:href]').read
       end
     rescue => e
       case e
       when OpenURI::HTTPError
         # do something
       when SocketError
         # do something else
       else
         raise e
       end
      rescue SystemCallError => e
       if e === Errno::ECONNRESET
        # do something else
       else
        raise e
       end
     end
   end

Я не знаю ни одного способа проверить соединение, не открывая его и не пытаясь, так что спасение от этих ошибок было бы единственным способом, о котором я могу думать. Следует помнить, что OpenURI :: HTTPError и SocketError являются подклассами StandardError, тогда как Errno :: ECONNRESET является подклассом SystemCallError. Так что спасите => e не поймает Errno :: ECONNRESET.

0 голосов
/ 13 декабря 2012

Мне удалось решить эту проблему с помощью условного оператора if / else, чтобы проверить возвращаемое значение действия для «fail»:

def controller_action
    url = "some_API"
    response = open(url).read
    data = JSON.parse(response)["data"]
    if response["status"] == "failure"
        redirect_to :action => "home" 
    else
        do_something_else
    end
end
...