如何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 ;