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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10687099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:30:45  来源:igfitidea点击:

How to test if a URL string is absolute or relative?

javascriptjquerystringurl

提问by TruMan1

How can I test a URL if it is a relative or absolute path in Javascript or jQuery? I want to handle accordingly depending if the passed in URL is a local or external path.

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

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

采纳答案by strah

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

For protocol relative urls, use this regex:

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

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

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

回答by Geo

FAST

快速地

If you only need to test for http://or https://then the most efficientway is:

如果您只需要测试http://orhttps://那么最有效的方法是:

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


UNIVERSAL

普遍的

However, I would suggest a more universal, non case-sensitive, protocol-agnosticapproach:

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

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


Explain the RegExp

解释正则表达式

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

^- beginning of the string
(?:- beginning of a non-captured group
[a-z]+- any character of 'a' to 'z' 1 or more times
:- string (colon character)
)?- end of the non-captured group. Group appearing 0 or 1 times
//- string (two forward slash characters)
'i'- non case-sensitive flag

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

回答by Philipp

Original Answer

原答案

A very fastand very flexiblecheck is:

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

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

This will recognize an absolute URL, if:

这将识别绝对 URL,如果:

  • URL contains "://" anywhere afterthe first character, or
  • URL starts with "//" (protocol relative)
  • URL第一个字符之后的任何位置包含“://” ,或
  • URL 以“//”开头(协议相关)


  • No regex.
  • No jQuery or other dependency.
  • No hardcoded protocol names that make the condition case sensitive.
  • No string manipulation (e.g. toLowerCase or similar).
  • Only checks for "relative or absolute" but does not make any other sanity checks, can be used for web URLs or any internal protocol.
  • 没有正则表达式。
  • 没有 jQuery 或其他依赖项。
  • 没有使条件区分大小写的硬编码协议名称。
  • 没有字符串操作(例如 toLowerCase 或类似的)。
  • 仅检查“相对或绝对”,但不进行任何其他健全性检查,可用于 Web URL 或任何内部协议。


Update 1 (full function example)

更新 1(全功能示例)

Here is a quick functionthat returns true/false for the given URL:

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

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

And same in ES6:

在 ES6 中也是如此:

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


Update 2 (URLs inside URL param)

更新 2(URL 参数中的 URL)

To additionally address URLs in format /redirect?target=http://example.orgI recommend to use this code:

要另外以格式寻址 URL,/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
}

And the same in short form and ES 6

短格式和 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)

Here are some test cases:

下面是一些测试用例:

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


Update 3 (clarify relative URLs)

更新 3(澄清相对 URL)

I've seen a few comments about invalid output:

我看到了一些关于无效输出的评论:

  • Solution returns false for localhost
  • Answer fails on http:example.com
  • 解决方案返回 false localhost
  • 回答失败 http:example.com

However, those URLs are indeed relative URLs. It's easy to test:

但是,这些 URL 确实是相对 URL。测试很容易:

  1. Create some folders on your localhost webroot, say a/b/c/
  2. Create an index.html file and place following link into it: <a href="localhost">test</a>
  3. Open the index page in your browser: http://localhost/a/b/c/index.htmland click on the link. You will end on http://localhost/a/b/c/localhost(and not on http://localhost)
  4. Same happens when placing the link http:example.cominto your index.html file. You end on http://localhost/a/b/c/example.cominstead of http://example.com
  1. 在 localhost webroot 上创建一些文件夹,比如 a/b/c/
  2. 创建一个 index.html 文件并将以下链接放入其中: <a href="localhost">test</a>
  3. 在浏览器中打开索引页面:http://localhost/a/b/c/index.html并单击链接。您将以http://localhost/a/b/c/localhost 结束(而不是http://localhost
  4. 将链接http:example.com放入 index.html 文件时也会发生同样的情况。您以http://localhost/a/b/c/example.com而不是http://example.com结尾

回答by SLaks

Use a regex:

使用正则表达式:

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

回答by Evan

Even more Universal RFC-compliant URI approach:

更通用的 RFC 兼容 URI 方法:

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

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

The other solutions listed here would fail for links like mailto:[email protected]

此处列出的其他解决方案对于类似的链接将失败 mailto:[email protected]

RFC 3986 defines a Schemeas:

RFC 3986 将Scheme定义为:

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

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

3.1. Schemehttps://tools.ietf.org/html/rfc3986#section-3.1

3.1. 方案https://tools.ietf.org/html/rfc3986#section-3.1

While the protocol-relative url is technically valid as per section 4.2, Paul Irish has swung back the other way and considers this an anti-pattern. See http://www.paulirish.com/2010/the-protocol-relative-url/

虽然根据第 4.2 节,相对于协议的 url 在技术上是有效的,但 Paul Irish 反其道而行之,并认为这是一种反模式。见http://www.paulirish.com/2010/the-protocol-relative-url/

4.2. Relative Referencehttp://tools.ietf.org/html/rfc3986#section-4.2

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

If you'd like the regex without protocol-relative url's use:

如果您想要不使用协议相关 url 的正则表达式:

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

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

To see a full list of other types of valid uri edge cases, check out the list here: https://en.wikipedia.org/wiki/URI_scheme

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

回答by rgtk

Nowdays, when a lot of services use protocol-relative URL(eg. //cdn.example.com/libary.js), this method is safer:

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

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

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

回答by koppor

Don't use low-level stuff like regexp etc. These things have been solved by so many other people. Especially the edge cases.

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

Have a look at URI.js, it should do the job: http://medialize.github.io/URI.js/docs.html#is

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

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

回答by davids

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

EDIT:

编辑:

With the next regular expression, you can even check if the link goes to the same domain or to an external one:

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

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

回答by Brad

Depending on your needs, I think that a more reliable way to determine this is to use the built-in URL interfaceto construct a couple URL objects and compare origins.

根据您的需要,我认为更可靠的确定方法是使用内置的 URL 接口来构建几个 URL 对象并比较来源。

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

This allows the browser to parse and figure all this out for you, without having to worry about the side effects of edge cases.

这允许浏览器为您解析和计算所有这些,而不必担心边缘情况的副作用。

回答by Etienne Martin

Here's a pretty robust solution for the browser environment:

这是浏览器环境的一个非常强大的解决方案:

Let the browser handle everything.No need for some complicated/error prone regexes.

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

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