如何测试URL字符串是绝对的还是相对的?

时间:2012-05-21 14:23:30

标签: javascript jquery string url

如果它是Javascript或jQuery中的相对路径或绝对路径,我如何测试URL?我希望相应处理,具体取决于传入的URL是本地路径还是外部路径。

if (urlString starts with http:// or https://)
 //do this

14 个答案:

答案 0 :(得分:131)

FAST

如果您只需要测试http://https://,那么最有效的方式是:

if (urlString.indexOf('http://') === 0 || urlString.indexOf('https://') === 0)

UNIVERSAL

但是,我建议使用更通用,不区分大小写,与协议无关的方法:

var r = new RegExp('^(?:[a-z]+:)?//', 'i');
r.test('http://example.com'); // true - regular http absolute URL
r.test('HTTP://EXAMPLE.COM'); // true - HTTP upper-case absolute URL
r.test('https://www.exmaple.com'); // true - secure http absolute URL
r.test('ftp://example.com/file.txt'); // true - file transfer absolute URL
r.test('//cdn.example.com/lib.js'); // true - protocol-relative absolute URL
r.test('/myfolder/test.txt'); // false - relative URL
r.test('test'); // false - also relative URL

解释RegExp

^(?:[a-z]+:)?//

^ - 字符串的开头
(?: - 未捕获组的开始 [a-z]+ - 'a'到'z'的任何字符1次或更多次
: - 字符串(冒号)
)? - 未捕获组的结束。组出现0或1次
// - 字符串(两个正斜杠字符)
'i' - 不区分大小写的标记

答案 1 :(得分:29)

var pat = /^https?:\/\//i;
if (pat.test(urlString))
{
    //do stuff
}

对于协议相对网址,请使用此正则表达式:

/^https?:\/\/|^\/\//i

答案 2 :(得分:17)

使用正则表达式:

if (/^(?:[a-z]+:)?\/\//i.test(url))

答案 3 :(得分:13)

非常快速且非常灵活检查:

if (url.indexOf('://') > 0 || url.indexOf('//') === 0 ) {
    // URL is absolute; either "http://example.com" or "//example.com"
} else {
    // URL is relative
}

这将识别绝对URL,如果:

  • 网址包含"://" 第一个字符后的任何地方,或
  • 网址以" //"开头(协议相对)
  • 没有正则表达式。
  • 没有jQuery或其他依赖。
  • 没有使条件区分大小写的硬编码协议名称。
  • 没有字符串操作(例如toLowerCase或类似)。
  • 仅检查"相对或绝对"但不进行任何其他健全性检查,可用于网址或任何内部协议。

<强>更新

这是一个快速函数,它返回给定URL的true / false:

function isUrlAbsolute(url) { 
    return (url.indexOf('://') > 0 || url.indexOf('//') === 0);
}

在ES6中也一样:

const isUrlAbsolute = (url) => (url.indexOf('://') > 0 || url.indexOf('//') === 0)

更新2

要另外处理格式为/redirect?target=http://example.org的网址,我建议使用此代码:

function isUrlAbsolute(url) {
    if (url.indexOf('//') === 0) {return true;} // URL is protocol-relative (= absolute)
    if (url.indexOf('://') === -1) {return false;} // URL has no protocol (= relative)
    if (url.indexOf('.') === -1) {return false;} // URL does not contain a dot, i.e. no TLD (= relative, possibly REST)
    if (url.indexOf('/') === -1) {return false;} // URL does not contain a single slash (= relative)
    if (url.indexOf(':') > url.indexOf('/')) {return false;} // The first colon comes after the first slash (= relative)
    if (url.indexOf('://') < url.indexOf('.')) {return true;} // Protocol is defined before first dot (= absolute)
    return false; // Anything else must be relative
}

以简短的形式和ES 6

相同
// Traditional JS, shortened
function isUrlAbsolute(url) {
    return url.indexOf('//') === 0 ? true : url.indexOf('://') === -1 ? false : url.indexOf('.') === -1 ? false : url.indexOf('/') === -1 ? false : url.indexOf(':') > url.indexOf('/') ? false : url.indexOf('://') < url.indexOf('.') ? true : false;
}

// ES 6
const isUrlAbsolute = (url) => (url.indexOf('//') === 0 ? true : url.indexOf('://') === -1 ? false : url.indexOf('.') === -1 ? false : url.indexOf('/') === -1 ? false : url.indexOf(':') > url.indexOf('/') ? false : url.indexOf('://') < url.indexOf('.') ? true : false)

以下是一些测试用例:

// Test
console.log( isUrlAbsolute('http://stackoverflow.com') ) // -> true
console.log( isUrlAbsolute('//stackoverflow.com') ) // -> true
console.log( isUrlAbsolute('stackoverflow.com') ) // -> false
console.log( isUrlAbsolute('Ftp://example.net') ) // -> true
console.log( isUrlAbsolute('/redirect?target=http://example.org') ) // -> false

答案 4 :(得分:9)

现在,当许多服务使用protocol-relative URL(例如 // cdn.example.com/libary.js )时,此方法更安全:

var isAbsolute = new RegExp('^([a-z]+://|//)', 'i');

if (isAbsolute.test(urlString)) {
  // go crazy here
}

答案 5 :(得分:7)

更符合通用RFC的URI方法:

(?:^[a-z][a-z0-9+.-]*:|\/\/) regex explanation

此处列出的其他解决方案对于mailto:evan@nylas.com

等链接会失败

RFC 3986将 Scheme 定义为:

scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

<强> 3.1。方案 https://tools.ietf.org/html/rfc3986#section-3.1

虽然协议相对网址在技术上是有效的,根据第4.2节,保罗爱尔兰已经转回另一种方式并认为这是一种反模式。见http://www.paulirish.com/2010/the-protocol-relative-url/

<强> 4.2。相对参考 http://tools.ietf.org/html/rfc3986#section-4.2

如果您不喜欢使用协议相关网址的正则表达式:

^[a-z][a-z0-9+.-]*:

要查看其他类型的有效uri边缘案例的完整列表,请查看此处的列表:https://en.wikipedia.org/wiki/URI_scheme

答案 6 :(得分:5)

var external = RegExp('^(https?:)?//');
if(external.test(el)){
    // do something
}

编辑:

使用下一个正则表达式,您甚至可以检查链接是转到同一个域还是外部链接:

var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')');
if(external.test(el)){
    // do something
}

答案 7 :(得分:4)

不要使用像regexp等低级别的东西。这些东西已经被很多其他人解决了。特别是边缘情况。

看看URI.js,它应该完成这项工作:http://medialize.github.io/URI.js/docs.html#is

var uri = new URI("http://example.org/");
uri.is("absolute") === true;

答案 8 :(得分:2)

根据您的需求,我认为一种更可靠的确定方法是使用built-in URL interface来构造几个URL对象并比较来源。

new URL(document.baseURI).origin === new URL(urlToTest, document.baseURI).origin;

这使浏览器可以为您解析并找出所有这些信息,而不必担心边缘情况的副作用。

答案 9 :(得分:1)

var adress = 'http://roflmao.com';
if (adress.substr(0,7) == 'http://' || adress.substr(0,8) == 'https://') {
    //
}

答案 10 :(得分:1)

当点击甚至发生在超链接上时,将会调用以下函数,即&#39; a&#39;标签如果标签包含url将是相对的或包含相同的主机然后新页面将被加载到相同的浏览器选项卡中,如果它包含不同的URL,则页面将加载到新的浏览器选项卡

jQuery(document).ready(function() {
    $('a').click(function(){

        var a = this;
        var a_href = $(this).attr('href');
        var regex = new RegExp('^(?:[a-z]+:)?//', 'i');     

        if(a.host == location.host || regex.test(a_href) == false){
            a.target = '_self';
        }else{
            a.target = '_blank';
        }
    }); 
});

答案 11 :(得分:0)

以下是解决问题的防弹方法:

让浏览器为我们处理一切。不需要一些复杂/容易出错的正则表达式。

const isAbsoluteUrl = (url) => {
  const link = document.createElement('a');
  link.href = url;
  return link.origin + link.pathname + link.search + link.hash === url;
};

不幸的是,在nodejs环境中不起作用。

答案 12 :(得分:0)

您可以使用try,catch块来解决此问题。除了使用正则表达式,您还可以在每一步使用URL接口。

isExternalUrl (urlString) {
  try {
    const url = new URL(urlString) // THROW ON MISSING SCHEME

    // DOES THIS URL ORIGINATE FROM THIS WEBSITE?
    if (url.origin !== new URL(document.URL, document.baseURI).origin) {
      return true // IS EXTERNAL URL
    }
  } catch (_e) {
    // THROWS WHEN URL DOES NOT HAVE A SCHEME
    new URL(urlString, document.baseURL) // THROW AN EXCEPTION IF THE URL IS TRULY MALFORMED IN SOME WAY
  }

  return false
}

答案 13 :(得分:-1)

var isExternalURL = url.toLowerCase().indexOf('http://') === 0 || url.toLowerCase().indexOf('https://') === 0 ;