From 264e30726a4cd9d95cf9b3caf603ed40fc50b1c2 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sat, 18 Jan 2025 00:59:37 +0800 Subject: [PATCH] Perf: make `normalizeDomain` faster --- Build/constants/loose-tldts-opt.ts | 11 +++++++---- Build/lib/normalize-domain.ts | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Build/constants/loose-tldts-opt.ts b/Build/constants/loose-tldts-opt.ts index 19c4959f..e51021c5 100644 --- a/Build/constants/loose-tldts-opt.ts +++ b/Build/constants/loose-tldts-opt.ts @@ -1,6 +1,6 @@ import type * as tldts from 'tldts'; -export const looseTldtsOpt: Parameters[1] = { +export const looseTldtsOpt: NonNullable[1]> = { allowPrivateDomains: false, extractHostname: false, validateHostname: false, @@ -8,12 +8,15 @@ export const looseTldtsOpt: Parameters[1] = { mixedInputs: false }; -export const loosTldOptWithPrivateDomains: Parameters[1] = { +export const loosTldOptWithPrivateDomains: NonNullable[1]> = { ...looseTldtsOpt, allowPrivateDomains: true }; -export const normalizeTldtsOpt: Parameters[1] = { +export const normalizeTldtsOpt: NonNullable[1]> = { allowPrivateDomains: true, - detectIp: true + // in normalizeDomain, we only care if it contains IP, we don't care if we need to extract it + // by setting detectIp to false and manually check ip outside tldts.parse, we can skip the tldts + // inner "extractHostname" call + detectIp: false }; diff --git a/Build/lib/normalize-domain.ts b/Build/lib/normalize-domain.ts index 093d415a..8837ae45 100644 --- a/Build/lib/normalize-domain.ts +++ b/Build/lib/normalize-domain.ts @@ -3,14 +3,21 @@ // import tldts from 'tldts-experimental'; import tldts from 'tldts'; import { normalizeTldtsOpt } from '../constants/loose-tldts-opt'; +import { isProbablyIpv4, isProbablyIpv6 } from 'foxts/is-probably-ip'; type TldTsParsed = ReturnType; /** * Skipped the input non-empty check, the `domain` should not be empty. */ -export function fastNormalizeDomain(domain: string, parsed: TldTsParsed = tldts.parse(domain, normalizeTldtsOpt)) { - if (parsed.isIp) return null; +export function fastNormalizeDomain(domain: string, parsed: TldTsParsed | null = null) { + // We don't want tldts to call its own "extractHostname" on ip, bail out ip first. + // Now ip has been bailed out, we can safely set normalizeTldtsOpt.detectIp to false. + if (isProbablyIpv4(domain) || isProbablyIpv6(domain)) { + return null; + } + + parsed ??= tldts.parse(domain, normalizeTldtsOpt); // Private invalid domain (things like .tor, .dn42, etc) if (!parsed.isIcann && !parsed.isPrivate) return null; @@ -20,9 +27,11 @@ export function fastNormalizeDomain(domain: string, parsed: TldTsParsed = tldts. export function normalizeDomain(domain: string, parsed: TldTsParsed | null = null) { if (domain.length === 0) return null; - parsed ??= tldts.parse(domain, normalizeTldtsOpt); + if (isProbablyIpv4(domain) || isProbablyIpv6(domain)) { + return null; + } - if (parsed.isIp) return null; + parsed ??= tldts.parse(domain, normalizeTldtsOpt); // Private invalid domain (things like .tor, .dn42, etc) if (!parsed.isIcann && !parsed.isPrivate) return null;