Detect whether a string isn't a URL in JavaScript?

For example:

You have this string: var x = "/windows/far/away/foo.jpg"

How I now if that string is a URL or no?

What I need to do is:

if (x.charAt(0) == '/') {
   x = "http://www.example.com/" + x;
}
else {
   x = "http://www.example.com/one/two/three" + x;
}

The problem here is: What will happens when x will be a URL? like:

x = "http://www.externalpage.com/foo.jpg";

As you can see, x.charAt(0) is 'h' and the result will be:

http://www.example.com/one/two/threehttp://www.externalpage.com/foo.jpg

Now, the solution "maybe" like this:

if (is_valid_url( x )) {
 ....
}
else {
 ....
}

I'm using this function for this:

function is_valid_url(str) {
  var pattern = new RegExp('^(https?:\/\/)?'+ // protocol
    '((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|'+ // domain name
    '((\d{1,3}\.){3}\d{1,3}))'+ // OR ip (v4) address
    '(\:\d+)?(\/[-a-z\d%_.~+]*)*'+ // port and path
    '(\?[;&a-z\d%_.~+=-]*)?'+ // query string
    '(\#[-a-z\d_]*)?$','i'); // fragment locater
  if(!pattern.test(str)) {
    alert("Please enter a valid URL.");
    return false;
  } else {
    return true;
  }
}

But this function only works with http and https, this will not work with other schemes like ftp or another....

I hope you understand the problem and bring me a solution. Thanks.

Upvotes: 0

Views: 1340

Answers (4)

Paul S.
Paul S.

Reputation: 66304

Similar to the answer of Lee Kowalkowski, I'd suggest using an <a> element to "make the browser do the work for you". This means that no GET request is fired, protecting you and your users from possible malicious entries during any verify step. It does, however, mean you don't know if the URL points to a real place.

function fixURL(str) {
    var a = document.createElement('a');
    a.href = str;
    return a.href;
}


fixURL('foo/bar');       // "https://stackoverflow.com/questions/16295050/foo/bar"
fixURL('/foo/bar');      // "https://stackoverflow.com/foo/bar"
fixURL('ftp://foo/bar'); // "ftp://foo/bar"

After this step you might also want to check against known "bad" URLs (possibly do that server-side).

Upvotes: 1

Replaced the protocol with ((news|(ht|f)tp(s?)):\/\/) that will match news://, http://, https://, ftp://

function is_valid_url(str) {
  var pattern = new RegExp('^((news|(ht|f)tp(s?)):\\/\\/)'+ // protocol
    '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
    '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
    '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
    '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
    '(\\#[-a-z\\d_]*)?$','i'); // fragment locater
  if(!pattern.test(str)) {
    alert("Please enter a valid URL.");
    return false;
  } else {
    return true;
  }
}

Upvotes: 0

Lee Kowalkowski
Lee Kowalkowski

Reputation: 11751

It looks like you actually want to normalise an image's URL, i.e. whatever string you are given, you want to convert to an absolute URL. I'd do this:

var x = /* insert arbitrary string here */;
var img = document.createElement('img');
img.src = x;
var absoluteUrl = img.src;

Let the browser do the grunt work.

If this is specific to images, you can also use the img.onload and img.onerror events to detect whether the URL references an image.

Upvotes: 1

Guffa
Guffa

Reputation: 700192

To make it work with other protocols, just replace https? in the pattern with an expression that matches any protocols you want, like:

var pattern = new RegExp('^((http|https|ftp|gopher|ssh|telnet):\/\/)?'+ // protocol

Upvotes: 3

Related Questions