0

I used to have a working code in my Admin Panel , checking if a url inputed existed and giving a friendly message to the Administrator in case it did not..

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

It works great when the address ("http://www.example.com" in the example above) exists, that it to say sends back a 200 code, but as soon as I have a non existing address such as http://www.examplenotexistingotallyfake.com, it should send a 404 code and display ""We have a problem ! Response code:" but it fails with the error message:

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'

I verified this by opening my Rails console (Rails c) and if I type:

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

I get the same error message:

 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'

How can it work for correct urls and not for non-existing addreses? it should just work but send me back a 404 code, shouldn't it?

I can only see the upgrade to Ubutun 16.04 i made a few days ago, that might have tampered with some critical dns/localhost settings as the source of this issue but not 100% totally sure.

EDIT

After some suggestions, I now try to avoid the app crashing by rescuing this

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

but the app still crashes with a socket Error message

Mathieu
  • 4,587
  • 11
  • 57
  • 112

2 Answers2

3

That's the correct behaviour.

The problem there is that examplenotexistingotallyfake.com doesn't exists in the DNSs entries.

If you look at the description of what the 404: https://en.wikipedia.org/wiki/HTTP_404

to indicate that the client was able to communicate with a given server, but the server could not find what was requested.

So, in order to get the 404 code you'll need first to be able to communicate with the server in question.

You can double check this behaviour using chrome or even curl, visiting the following urls: examplenotexistingotallyfake.com or google.com/missing

Each will give a different result.

in curl:

$ 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

If you want your code to behave in the same way (even though I'd suggest that give the user a different message, you can do the following):

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
Jonathan Duarte
  • 753
  • 5
  • 9
  • Thanks a lot, feeling stupid. Seems obvious now! I treid with a real 404 (ex: https://www.amazon.fr/dshusdhds) and not dns non existing domain, and it works fine – Mathieu Jan 12 '18 at 09:47
  • how can I show a different message ? I'd like to make the app not crash with an error "SocketError: Failed to open TCP connection to examplenotexistingotally" but instead stay with a working app but give the message "this web adress does not exist (dns issue)" – Mathieu Jan 12 '18 at 09:50
  • I am using the code you put at the bottom, and I'm still getting the app crash with a big error message "Failed to open TCP connection to www.dssddsdsdsn.com:443 (getaddrinfo: Name or service not known)" – Mathieu Jan 12 '18 at 09:53
  • I'm trying to add "rescue SocketError => e" but app still crashes – Mathieu Jan 12 '18 at 09:59
  • putting the new code in Edit, but still my app crashed – Mathieu Jan 12 '18 at 10:02
  • I'm using the following code: https://gist.github.com/jonduarte/faa91865ecc904bc9a503d32657e804c and it's working as expected. Are you using it differently? – Jonathan Duarte Jan 12 '18 at 10:05
  • your code is working if address is www.fakeurl.com but not if its like in my case beginning with the protocol "http://www.fakeurl.com". In that case it still throws Socket Error – Mathieu Jan 12 '18 at 10:53
  • i'm just going to remove the http using some tehcnique:) – Mathieu Jan 12 '18 at 10:54
  • modified slightly your code to stripped_url = url.sub(/^https?\:\/\/(www.)?/,'') url_response = get_url_response(stripped_url).code.to_i – Mathieu Jan 12 '18 at 11:11
  • correction to previous comment :"your code is working if address is www.fakeurl.com but not if its like in my case beginning with the protocol http such as http .www.fakeurl.com". In that case it still throws Socket Error – Mathieu Jan 12 '18 at 11:44
  • You don't need to strip out the url. You can rescue both exceptions at the same time, like so: https://gist.github.com/jonduarte/faa91865ecc904bc9a503d32657e804c – Jonathan Duarte Jan 12 '18 at 12:22
  • Extended your suggestion to a new question on SO: https://stackoverflow.com/questions/48579499/adding-open-and-read-timeout-error-and-notifcation-to-nethttp – Mathieu Feb 02 '18 at 09:26
0

Its not an issue , the site you are looking for it doesn't exists and can't be reached.

So it will give DNS address is not found issue when you try to hit it directly.Thats why the error: It directly gives socketError : getaddrinfo: Name or service not known You need to handle this.

But if you want 404 status code, you will get it when the site(address) is present and the page inside that site is not.

To get 404 your address should be valid and error will raise if The requested URL /examples was not found on this server.

teju c
  • 336
  • 2
  • 8
  • Thanks a lot, feeling stupid. Seems obvious now! I treid with a real 404 (ex: amazon.fr/dshusdhds) and not dns non existing domain, and it works fine – Mathieu Jan 12 '18 at 09:54
  • i juts wish now to avoid then the app crashing with a big Socket Error. Putting the new code in Edit, but still my app crashed – Mathieu Jan 12 '18 at 10:04