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

Javascript 如何测试URL字符串是绝对的还是相对的?,javascript,jquery,string,url,Javascript,Jquery,String,Url,在Javascript或jQuery中,如果URL是相对路径或绝对路径,如何测试它?我希望根据传入的URL是本地路径还是外部路径进行相应的处理 if (urlString starts with http:// or https://) //do this 它不应该以斜杠或哈希开头,如果前面没有问号或哈希,它也不应该包含双斜杠?我不会用单个regexp测试它,匹配“无双斜杠”将非常复杂 将更容易、更清晰、更快。使用正则表达式: if (/^(?:[a-z]+:)?\/\//i.test(ur

在Javascript或jQuery中,如果URL是相对路径或绝对路径,如何测试它?我希望根据传入的URL是本地路径还是外部路径进行相应的处理

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

它不应该以斜杠或哈希开头,如果前面没有问号或哈希,它也不应该包含双斜杠?我不会用单个regexp测试它,匹配“无双斜杠”将非常复杂

将更容易、更清晰、更快。

使用正则表达式:

if (/^(?:[a-z]+:)?\/\//i.test(url))
对于协议相关URL,请使用以下正则表达式:

/^https?:\/\/\124; ^\/\///i

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

使用下一个正则表达式,您甚至可以检查链接是否指向同一个域或外部域:

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

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

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

if (isAbsolute.test(urlString)) {
  // go crazy here
}
快速的 如果您只需要测试
http://
https://
,那么最有效的方法是:


普遍的 但是,我建议采用一种更普遍、不区分大小写、协议不可知的方法:

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”的字符出现1次或以上
-字符串(冒号字符)
)?
-未捕获组的结尾。组出现0或1次
/
-字符串(两个正斜杠字符)

'i'
-不区分大小写的标志

不要使用诸如regexp等低级的东西。这些问题已经被很多人解决了。尤其是边缘情况

看一看,它应该完成以下任务:

更通用的RFC兼容URI方法:
(?:^[a-z][a-z0-9+.-]*:\/)

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

RFC 3986将方案定义为:

scheme=ALPHA*(ALPHA/数字/“+”/“-”/”)

3.1。方案

根据第4.2节,协议相对url在技术上是有效的,但Paul Irish回过头来认为这是一种反模式。看

4.2。相对参考

如果希望正则表达式不使用协议相对url:

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


要查看其他类型的有效uri边缘情况的完整列表,请查看此处的列表:

当超链接(即“a”标记)上发生单击事件时,将调用以下函数如果标记包含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';
        }
    }); 
});
原始答案 非常快速和非常灵活的检查是:

if (url.indexOf('://') > 0 || url.indexOf('//') === 0 ) {
    // URL is absolute; either "http://example.com" or "//example.com"
} else {
    // URL is relative
}
这将识别一个绝对URL,如果:

  • URL在第一个字符后的任意位置包含“:/”,或
  • URL以“/”开头(协议相关)

  • 没有正则表达式
  • 没有jQuery或其他依赖项
  • 没有使条件区分大小写的硬编码协议名称
  • 无字符串操作(例如toLowerCase或类似)
  • 仅检查“相对或绝对”,但不进行任何其他健全性检查,可用于web URL或任何内部协议

更新1(完整功能示例) 下面是一个快速的函数,它返回给定URL的真/假:

function isUrlAbsolute(url) { 
    return (url.indexOf('://') > 0 || url.indexOf('//') === 0);
}
在ES6中也是如此:

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

更新2(URL参数内的URL) 以
/redirect?目标格式另外寻址URL=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
}

更新3(澄清相关URL) 我看到一些关于无效输出的评论:

  • 对于
    localhost
  • 在http:example.com上回答失败
然而,这些URL实际上是相对URL。很容易测试:

  • 在本地主机webroot上创建一些文件夹,例如
    a/b/c/
  • 创建index.html文件并将以下链接放入其中:
  • 在浏览器中打开索引页:并单击链接。你将在(而不是)结束
  • 将链接
    http:example.com
    放入index.html文件时也会发生同样的情况。你结束于,而不是

  • 以下是针对浏览器环境的一个非常健壮的解决方案:

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

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

    上述两种解决方案均未解决黑客进入
    /\/example.com
    /\\\/example.com
    重定向\u url
    黑客攻击。这是我用来确定重定向url是否是相对的:

    var isRelative = !redirectUrl.match(/(\:|\/\\*\/)/);  // Don't allow "//" (with optional "\"'s) or ":"
    

    根据您的需要,我认为确定这一点的更可靠的方法是使用构造一对URL对象并比较来源

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

    这样,浏览器就可以为您分析并解决所有这些问题,而不必担心边缘案例的副作用。

    您可以使用try,catch块来帮助解决这一问题。您可以在每个步骤中使用接口,而不是使用正则表达式

    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
    }
    

    没错。我不使用正则表达式,因为我很烂。无论如何,在现代浏览器中Http不会被转换成Http吗?您需要转义主机名中几乎肯定会出现的
    字符。否则,Fo..ExpPule.com也将匹配FooExpRult.COME回答所提出的问题,但您可能还想考虑从“代码> //< /代码>开始。如果URL包含“文件://”?繁荣悲剧。来自@Philipp的答案更可靠。接受的答案无效,至少在2019年。Chrome乐于接受http:example.com。这似乎是最普遍的答案。只缺少与协议相关的URL(例如//cdn.example.com/libary.js),尽管问题只提到http和https,这是一种通用的解决方案
    const isUrlAbsolute = (url) => (url.indexOf('://') > 0 || url.indexOf('//') === 0)
    
    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
    }
    
    // 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
    
    var isExternalURL = url.toLowerCase().indexOf('http://') === 0 || url.toLowerCase().indexOf('https://') === 0 ;
    
    const isAbsoluteUrl = (url) => {
      const link = document.createElement('a');
      link.href = url;
      return link.origin + link.pathname + link.search + link.hash === url;
    };
    
    var isRelative = !redirectUrl.match(/(\:|\/\\*\/)/);  // Don't allow "//" (with optional "\"'s) or ":"
    
    new URL(document.baseURI).origin === new URL(urlToTest, document.baseURI).origin;
    
    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
    }