Fastest way to detect external URLs
If you consider a URL being external if either the scheme, host or port is different, you could do something like this:
function isExternal(url) {
var match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);
if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== location.protocol) return true;
if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(":("+{"http:":80,"https:":443}[location.protocol]+")?$"), "") !== location.host) return true;
return false;
}
Update: I did some more research and found that using new URL
is easily fast enough, and IMO the most straight-forward way of doing this.
It is important to note that every method I've tried takes less than 1ms to run even on an old phone. So performance shouldn't be your primary consideration unless you are doing some large batch processing. Use the regex version if performance is your top priority.
These are the three methods I tried:
new URL
:
const isExternalURL = (url) => new URL(url).origin !== location.origin;
String.replace:
function isExternalReplace(url) {
const domain = (url) => url.replace('http://','').replace('https://','').split('/')[0];
return domain(location.href) !== domain(url);
}
Regex:
const isExternalRegex = (function(){
const domainRe = /https?:\/\/((?:[\w\d-]+\.)+[\w\d]{2,})/i;
return (url) => {
const domain = (url) => domainRe.exec(url)[1];
return domain(location.href) !== domain(url);
}
})();
Here are some basic tests I used to test performance: https://is-external-url-test.glitch.me/