Links to user-specified urls interpreted as relative urls

236 Views Asked by At

Sorry if this question has been answered elsewhere, but I've spent awhile looking with no luck.

In my web app, I ask users to specify urls to their blogs. However, they don't always put "http://" at the beginning of these urls. Elsewhere on the site, when I link to these urls, the browser interprets them as relative urls. e.g. if the user writes bobsblog.wordpress.com, the link goes to http://www.mydomain.com/bobsblog.wordpress.com.

One solution is to pre-populate the url field with "http://".

But a nicer solution would be to parse the url and add the scheme if the user hasn't. Does rails offer a good way to do this? I looked at the function URI::parse, but it doesn't seem to offer a good way of doing that.

2

There are 2 best solutions below

0
On BEST ANSWER

You could use URI.parse and check the scheme.

before_save :sanitize_url

def sanitize_url
  uri = URI.parse(url)
  self.url = "http://#{url}" if uri.scheme.blank?
rescue URI::InvalidURIError => e
  # not a parseable URI, so you need to handle that
end

Here some output

ree-1.8.7-2011.03 :035 > x = URI.parse "http://google.com"
 => #<URI::HTTP:0x1069720c8 URL:http://google.com> 
ree-1.8.7-2011.03 :036 > x.scheme
 => "http" 
ree-1.8.7-2011.03 :037 > y = URI.parse "google.com"
 => #<URI::Generic:0x1069672e0 URL:google.com> 
ree-1.8.7-2011.03 :038 > y.scheme
 => nil 
ree-1.8.7-2011.03 :039 > z = URI.parse "https://google.com"
 => #<URI::HTTPS:0x10695b8f0 URL:https://google.com> 
ree-1.8.7-2011.03 :040 > z.scheme
 => "https" 
1
On

Maybe in your model, you could have a method to return the URL as an absolute URL. If it doesn't start with "http://", just add it to the front.

def abs_url
    (url.start_with? "http://") ? url : ("http://" + url)
end

And in your view, just do something like @user.abs_url.


Edit: Oh, I didn't realize, but you probably wanted to do this upon submission. Similar logic can be done before the save. In that case:

before_save :abs_url
...
def abs_url
    url = (url.start_with? "http://") ? url : ("http://" + url)
end

And the URL will be saved with the "http://" in the front.