【问题标题】:Ruby 2.3/Rails - net uri not working anymore after update to Ubuntu 16.04Ruby 2.3/Rails - 更新到 Ubuntu 16.04 后,net uri 不再工作
【发布时间】:2018-01-12 18:03:58
【问题描述】:

我曾经在我的管理面板中有一个工作代码,检查输入的 url 是否存在,并在不存在的情况下向管理员发送友好消息..

def get_url_response(url)
    uri = URI(url)
    request = Net::HTTP.get_response(uri)
    return request
end

url_response = get_url_response("http://www.example.com").code
    if  url_response === "200" || url_response === "304"
       link_to http://www.example.com, http://www.example.com, target: :blank
    else                                                          
        status_tag("We have a problem ! Response code: "+url_response, :class => 'red')  
    end

当地址(上例中的“http://www.example.com”)存在时效果很好,它说发回一个 200 代码,但只要我有一个不存在的地址,例如http://www.examplenotexistingotallyfake.com,它应该发送 404 代码并显示“”我们有问题!响应代码:”但失败并显示错误消息:

SocketError: Failed to open TCP connection to examplenotexistingotallyfake.com:443 (getaddrinfo: Name or service not known)
from /home/mreisner/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/net/http.rb:882:in `rescue in block in connect'

我通过打开我的 Rails 控制台 (Rails c) 验证了这一点,如果我输入:

 Net::HTTP.get(URI('https://www.examplenotexistingotallyfake.com')).code

我收到同样的错误信息:

 SocketError: Failed to open TCP connection to examplenotexistingotallyfake.com:443 (getaddrinfo: Name or service not known)
from /home/mreisner/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/net/http.rb:882:in `rescue in block in connect'

它如何适用于正确的网址而不适用于不存在的地址?它应该可以工作,但给我发回 404 代码,不是吗?

我只能看到我几天前升级到 Ubutun 16.04,这可能已经篡改了一些关键的 dns/localhost 设置作为这个问题的根源,但不是 100% 完全确定。

编辑

经过一些建议,我现在尝试通过抢救这个来避免应用崩溃

def get_url_response(url)       
    begin
        uri = URI(url)
          request = Net::HTTP.get_response(uri)
          return request

        rescue SocketError => e
        puts "Got socket error: #{e}"
        end

  end

但应用程序仍然崩溃并显示套接字错误消息

【问题讨论】:

  • 你确定它以前工作过吗
  • 几天前我看到消息““我们有问题! " 所以我认为是但不是 100%

标签: ruby-on-rails ruby net-http


【解决方案1】:

这是正确的行为。

问题在于 DNS 条目中不存在 examplenotexistingotallyfake.com

如果你看一下404的描述:https://en.wikipedia.org/wiki/HTTP_404

表示客户 能够与给定的通信 服务器,但服务器找不到请求的内容。

因此,为了获得 404 代码,您首先需要能够与相关服务器进行通信。

您可以使用 chrome 甚至 curl 仔细检查此行为,访问以下网址:examplenotexistingotallyfake.com 或 google.com/missing

每个都会给出不同的结果。

在卷曲中:

$ curl -I examplenotexistingotallyfake.com
curl: (6) Could not resolve host: examplenotexistingotallyfake.com

# google
curl -I google.com/missing
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Content-Length: 1568
Date: Fri, 12 Jan 2018 09:25:27 GMT

如果您希望您的代码以相同的方式运行(即使我建议给用户一个不同的消息,您也可以执行以下操作):

require 'uri'
require 'net/http'
require 'ostruct'

def get_url_response(url)
  uri = URI(url)
  request = Net::HTTP.get_response(uri)
  return request
rescue Errno::ECONNREFUSED => e
  OpenStruct.new(code: 404)
end

【讨论】:

  • 非常感谢,感觉很愚蠢。现在看起来很明显!我使用真正的 404(例如:amazon.fr/dshusdhds)而不是 dns 不存在的域,它工作正常
  • 如何显示不同的消息?我想让应用程序不会因错误“SocketError:无法打开与 examplenotexistingotally 的 TCP 连接”而崩溃,而是继续使用正在运行的应用程序,但给出消息“此 Web 地址不存在(DNS 问题)”
  • 我正在使用您放在底部的代码,但我仍然收到应用程序崩溃并显示一条大错误消息“无法打开与 www.dssddsdsdsn.com:443 的 TCP 连接 (getaddrinfo:名称或服务未知)”
  • 我正在尝试添加“rescue SocketError => e”,但应用仍然崩溃
  • 将新代码放入编辑中,但我的应用仍然崩溃
【解决方案2】:

这不是问题,您要查找的站点不存在且无法访问。

所以当你尝试直接点击它时它会给出DNS address is not found 问题。这就是错误的原因: 它直接给socketError : getaddrinfo: Name or service not known你需要处理这个。

但是如果你想要404 status code,当站点(地址)存在并且该站点内的页面不存在时,你会得到它。

要获得404,您的地址应该是有效的,如果The requested URL /examples was not found on this server. 则会引发错误

【讨论】:

  • 非常感谢,感觉很愚蠢。现在看起来很明显!我使用真正的 404(例如:amazon.fr/dshusdhds)而不是 dns 不存在的域,它工作正常
  • 我现在只是希望避免应用程序因严重的套接字错误而崩溃。将新代码放入编辑中,但我的应用程序仍然崩溃
猜你喜欢
  • 2021-10-30
  • 2017-05-23
  • 2017-01-13
  • 1970-01-01
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
相关资源
最近更新 更多