@geek/tld
Version:
Extract the TLD/domain/subdomain parts of an URL/hostname against mozilla TLDs 'official' listing .
69 lines (46 loc) • 2.69 kB
JavaScript
"use strict";
var url = require('url');
var parse_url = function(remote_url, options) {
if(typeof remote_url == "string")
remote_url = url.parse(remote_url);
return parse_host(remote_url.hostname, options);
};
var tlds = null;
var parse_host = function(host, options) {
let allowPrivateTLD = options && options.allowPrivateTLD || false;
let allowUnknownTLD = options && options.allowUnknownTLD || false;
if(!tlds) {
tlds = require('./effective_tld_names.json');
tlds.combined = Object.assign({}, tlds.icann, tlds.private);
}
var parts = host.split(".");
var stack = "", tld_level = -1;
var roots = allowPrivateTLD ? tlds.combined : tlds.icann;
for(var i = parts.length - 1, part; i >= 0; i--) {
part = parts[i];
stack = stack ? part + "." + stack : part;
if(roots[stack])
tld_level = roots[stack];
}
if(tld_level == -1 ) {
const expression = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))/;
const is_ip = expression.test(host);
if( is_ip ){
return {
tld: 'IP_ADDRESS',
domain: host,
};
} else if( allowUnknownTLD) {
tld_level = 1;
}
}
if(parts.length <= tld_level || tld_level == -1)
throw new Error("Invalid TLD " + JSON.stringify({parts, tld_level, allowUnknownTLD}));
return {
tld : parts.slice(-tld_level).join('.'),
domain : parts.slice(-tld_level - 1).join('.'),
sub : parts.slice(0, (-tld_level - 1)).join('.'),
};
};
module.exports = parse_url;
module.exports.parse_host = parse_host;