37

In my rails application I need to verify if the URL given by a user is really an URL. I'm only concerned with the HTTP protocol (and perhaps HTTPS, I have not looked into that at all), which leads me to believe that there might something already in rails that can do this work for me.

If not: can you recommend a regex string that does this? I've found some after googling but they all seem to have a problem or two according to user comments.

Thanks

Emil Ahlbäck
  • 6,085
  • 8
  • 39
  • 54

2 Answers2

75

Use the URI library.

def uri?(string)
  uri = URI.parse(string)
  %w( http https ).include?(uri.scheme)
rescue URI::BadURIError, URI::InvalidURIError
  false
end

This is a very simple example. The advantage of using the URI library over a regular expression is that you can perform complex checks.

fatfrog
  • 2,118
  • 1
  • 23
  • 46
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • Actually now that I have written some tests with a bunch of different invalid URLs I found that this method validates "http://foo.invalid" as true. Perhaps I just need to fiddle around more? – Emil Ahlbäck Mar 16 '11 at 21:09
  • Because it actually is a valid URI. If you want to validate an URL, make sure the #path and #scheme exists. – Simone Carletti Mar 16 '11 at 22:48
  • It checks for a valid HTTP(s) URL scheme. – Simone Carletti Apr 11 '11 at 07:22
  • `%w(stringone stringtwo stringthree)` is a shortcut to create an array of given strings – Ashley May 20 '14 at 07:58
  • 1
    Using exceptions in this matter is overkill. Please use this answer: http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby (url =~ URI::regexp) – Dennis Feb 08 '17 at 13:31
  • @Dennis they do not do the same thing, OP asked for URL validation. Your solution only validates URI, they are not the same thing, and even validating URI with RegEx is not foolproof see https://stackoverflow.com/questions/161738. User entering "www.google.com" will pass this solution, and fail yours. – Andre Figueiredo Feb 07 '20 at 21:57
  • @AndreFigueiredo you are right indeed. I checked the solution again, but i don't see why the rescue clauses are necessary. A simple `uri?(some_var.to_s)` would solve. – Dennis Feb 08 '20 at 09:38
  • well, that depends on how and where the programmer want to handle handling exceptions for the internal logic... I, for instance, would just handle the exception with base exception aka `URI::Error` and return false. You could `.to_s` in the 1st line of the method to not externalize the responsibility of conversion to caller, but that would just take care of `BadURIError`, any other invalid URI would throw out `InvalidURIError` – Andre Figueiredo Feb 10 '20 at 14:38
  • @AndreFigueiredo yes of course it would, that's not the point. – Dennis Feb 19 '20 at 07:40
4

validates :url, :format => URI::regexp(%w(http https))

amit_saxena
  • 7,450
  • 5
  • 49
  • 64