如何testing一个URLstring是绝对的还是相对的?

我如何testing一个URL,如果它是在JavaScript或jQuery的相对或绝对path? 我想相应地处理,如果传入的URL是一个本地或外部path。

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

对于协议相关的URL,使用这个正则expression式:

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

快速

如果您只需要testinghttp://https://那么最有效的方法是:

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

普遍

但是,我会build议一个更普遍的,不区分大小写的协议不可知的方法:

 var r = new RegExp('^(?:[az]+:)?//', '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

 ^(?:[az]+:)?// 

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

使用正则expression式:

 if (/^(?:[az]+:)?\/\//i.test(url)) 

现在,当很多服务使用协议相关的URL (例如//cdn.example.com/libary.js )时,这种方法更安全:

 var isAbsolute = new RegExp('^([az]+://|//)', 'i'); if (isAbsolute.test(urlString)) { // go crazy here } 
 var external = RegExp('^(https?:)?//'); if(external.test(el)){ // do something } 

编辑:

用下一个正则expression式,你甚至可以检查链接是否进入相同的域或外部域:

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

一个非常快速和非常灵活的检查是:

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

如果符合以下条件,则会识别绝对url:

  • URL 第一个字符之后的任何地方包含“://”,或者
  • URL以“//”开头(协议相对)

  • 没有正则expression式。
  • 没有jQuery或其他依赖。
  • 没有使条件大小写敏感的硬编码协议名称。
  • 没有string操作(例如toLowerCase或类似的)。
  • 只检查“相对或绝对”,但不作任何其他健康检查,可用于url或任何内部协议。

更新

这是一个快速的函数,返回给定的URL的真/假:

 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格式的url,我build议使用以下代码:

 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, ie 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) 

以下是一些testing用例:

 // 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 

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

看看URI.js ,它应该做的工作: http : //medialize.github.io/URI.js/docs.html#is

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

更符合通用RFC标准的URI方法:

(?:^[az][a-z0-9+.-]*:|\/\/) 正则expression式解释

这里列出的其他解决scheme将失败的链接,如mailto:evan@nylas.com

RFC 3986将一个Scheme定义为:

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

3.1。 计划 https://tools.ietf.org/html/rfc3986#section-3.1

虽然协议相关的url在4.2节中在技术上是有效的,但是保罗·爱尔兰却反其道而行,认为这是一种反模式。 见http://www.paulirish.com/2010/the-protocol-relative-url/

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

如果你想要没有协议相关的URL的使用正则expression式:

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

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

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

下面的函数会在超链接上发生点击时被调用,即如果标签包含url,它将是相对的或者包含相同的主机,那么新的页面将被加载到相同的浏览器标签,如果它包含不同的url,那么页面将加载新的浏览器标签

 jQuery(document).ready(function() { $('a').click(function(){ var a = this; var a_href = $(this).attr('href'); var regex = new RegExp('^(?:[az]+:)?//', 'i'); if(a.host == location.host || regex.test(a_href) == false){ a.target = '_self'; }else{ a.target = '_blank'; } }); }); 
 var isExternalURL = url.toLowerCase().indexOf('http://') === 0 || url.toLowerCase().indexOf('https://') === 0 ;