Asset / node_modules /tldts-core /src /is-valid.ts
Really-amin's picture
Fix Futures analysis freshness clock skew and verify KuCoin fallback
3401f26 verified
Raw
History Blame Contribute Delete
3.12 kB
/**
* Implements fast shallow verification of hostnames. This does not perform a
* struct check on the content of labels (classes of Unicode characters, etc.)
* but instead check that the structure is valid (number of labels, length of
* labels, etc.).
*
* If you need stricter validation, consider using an external library.
*/
// KEEP IN SYNC with `extract-hostname.ts` `isValidHostnameChar` + its inline
// scan/verdict, which duplicate these structural rules to validate during
// extraction (a perf fusion). That copy additionally accepts A-Z (the host is
// not yet lowercased there) and folds in '-' / '_'. Any change to the accepted
// character set or the label/length rules here must be mirrored there.
function isValidAscii(code: number): boolean {
return (
(code >= 97 && code <= 122) || (code >= 48 && code <= 57) || code > 127
);
}
/**
* Check if a hostname string is valid. It's usually a preliminary check before
* trying to use getDomain or anything else.
*
* Beware: it does not check if the TLD exists.
*/
export default function (hostname: string): boolean {
if (hostname.length > 255) {
return false;
}
if (hostname.length === 0) {
return false;
}
if (
/*@__INLINE__*/ !isValidAscii(hostname.charCodeAt(0)) &&
hostname.charCodeAt(0) !== 46 && // '.' (dot)
hostname.charCodeAt(0) !== 95 // '_' (underscore)
) {
return false;
}
// Validate hostname according to RFC
let lastDotIndex = -1;
let lastCharCode = -1;
const len = hostname.length;
for (let i = 0; i < len; i += 1) {
const code = hostname.charCodeAt(i);
if (code === 46 /* '.' */) {
if (
// Check that previous label is < 63 bytes long (64 = 63 + '.')
i - lastDotIndex > 64 ||
// Check that previous character was not already a '.'
lastCharCode === 46 ||
// Check that the previous label does not end with '-' (RFC 1035 §2.3.1 LDH).
// '_' is intentionally NOT restricted: DNS allows any octet (RFC 2181 §11) and
// WHATWG URL does not treat '_' as a forbidden host code point.
lastCharCode === 45
) {
return false;
}
lastDotIndex = i;
} else if (
// A forbidden character in the label...
!(/*@__INLINE__*/ (isValidAscii(code) || code === 45 || code === 95)) ||
// ...or a '-' starting a label (the byte right after a '.'). A label must
// not begin with a hyphen (RFC 1034 §3.5 / RFC 1035 §2.3.1 LDH, as amended
// by RFC 1123 §2.1; cf. UTS #46 CheckHyphens). The first label is covered by
// the leading-character guard above; mirrors the trailing-'-' rule below.
(code === 45 && lastCharCode === 46)
) {
return false;
}
lastCharCode = code;
}
return (
// Check that last label is shorter than 63 chars
len - lastDotIndex - 1 <= 63 &&
// Check that the last character is an allowed trailing label character.
// Since we already checked that the char is a valid hostname character,
// we only need to check that it's different from '-'.
lastCharCode !== 45
);
}