【问题标题】:Ruby URL.parse errorRuby URL.parse 错误
【发布时间】:2011-09-21 05:35:00
【问题描述】:

这是我的红宝石程序

require 'net/http'
require 'uri'

begin
    url = URI.parse("http://google.com")
rescue Exception => err
    p err
    exit
end

http = Net::HTTP.new(url.host, url.port) 
res = http.head("/")
p res.code

它工作正常,但是如果我从 URL.parse() 中删除 http://,它会给我这个错误:

/usr/lib/ruby/1.9.1/net/http.rb:1196:in `addr_port': undefined method `+' for nil:NilClass (NoMethodError) ...
from /usr/lib/ruby/1.9.1/net/http.rb:1094:in `request'
from /usr/lib/ruby/1.9.1/net/http.rb:860:in `head'

处理异常的方法正确吗?

我知道 URL 可能不正确,但它应该引发异常 URI::InvalidURIError 而不是接受并继续程序?

【问题讨论】:

    标签: ruby exception net-library


    【解决方案1】:

    如果你说u = URI.parse('http://google.com'),你会得到一个URI::HTTPu.port 的默认值为80。如果你说u = URI.parse('google.com'),你会得到一个URI::Generic 和@ 987654326@ 将是 nilu.host

    所以,当你这样做时:

    url  = URI.parse('google.com')
    http = Net::HTTP.new(url.host, url.port)
    

    你真的在这样做:

    http = Net::HTTP.new(nil, nil)
    

    Net::HTTP 根本不喜欢这样。你可以试试这样的:

    if(str.to_s.empty?)
        # complain loudly about a missing str
    end
    begin
        url = URI.parse(str)
        url = URI.parse('http://' + str) if !url.scheme
    
        if(url.scheme != 'http' && url.scheme != 'https')
            # more complaining about bad input
        end
    
        http = Net::HTTP.new(url.host, url.port)
        #...
    rescue URI::Error => e
        # even yet more complaining
    end
    

    这类事情应该完全绕过异常并涵盖您可能感兴趣的其他一些事情。

    【讨论】:

      【解决方案2】:

      您必须专门捕获URI::InvalidURIError,因为它不是Exception 的后代。见:

      irb(main):002:0> URI::InvalidURIError.is_a?(Exception)
      => false
      

      因此,您的代码的修复方法是:

      begin
          url = URI.parse("http://google.com")
      rescue URI::InvalidURIError => err
          p err
          exit
      end
      

      【讨论】:

      • 感谢您的回答,但在 URI.parse("google.com") 时仍然没有发现错误
      • 哦,你是对的。我没有足够清楚地阅读您的问题,我的回答并没有真正回答它。尽管如此,它是该代码的有效修复=)。
      • @iKid,我添加了另一个答案来回答你的问题。
      【解决方案3】:

      正确的方法是根本不让任何异常发生,而是事先检查你的条件。像这样:

      require 'net/http'
      require 'uri'
      
      begin
          url = URI.parse("http://google.com")
      rescue URI::InvalidURIError => err
          p err
          exit
      end
      
      if url.host && url.port
          http = Net::HTTP.new(url.host, url.port) 
          res = http.head("/")
          p res.code
      else
              p 'Error parsing url'
      end
      

      【讨论】:

      • 这种方法只有在接收者接受 HEAD 请求时才有效。并非所有 Web 服务器都支持 HEAD 请求。
      • @rantler,虽然这是真的,但我的方法与头部请求无关。我的那部分答案是直接从 OP 的代码中复制的——我假设 OP 知道有问题的服务器响应 HEAD 请求,如果没有,那么这是一个完全独立的问题。这与我对问题的回答无关。
      猜你喜欢
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 2014-01-13
      • 1970-01-01
      • 2017-06-15
      • 2014-04-17
      • 1970-01-01
      相关资源
      最近更新 更多