mirror of
https://github.com/jakejarvis/rdapper.git
synced 2026-09-23 00:15:31 -04:00
Implement WHOIS referral chain collection and merging logic (fixes #11)
- Introduced `collectWhoisReferralChain` to gather WHOIS responses while avoiding contradictory data from registrars. - Updated `lookupDomain` to utilize the new chain collection method, ensuring TLD responses are prioritized. - Added `mergeWhoisRecords` function to consolidate WHOIS data from multiple sources. - Enhanced tests for referral handling and merging behavior, ensuring accurate data retention across scenarios.
This commit is contained in:
+32
-10
@@ -9,8 +9,12 @@ import {
|
||||
ianaWhoisServerForTld,
|
||||
parseIanaRegistrationInfoUrl,
|
||||
} from "./whois/discovery";
|
||||
import { mergeWhoisRecords } from "./whois/merge";
|
||||
import { normalizeWhois } from "./whois/normalize";
|
||||
import { followWhoisReferrals } from "./whois/referral";
|
||||
import {
|
||||
collectWhoisReferralChain,
|
||||
followWhoisReferrals,
|
||||
} from "./whois/referral";
|
||||
|
||||
/**
|
||||
* High-level lookup that prefers RDAP and falls back to WHOIS.
|
||||
@@ -32,7 +36,13 @@ export async function lookupDomain(
|
||||
|
||||
// If WHOIS-only, skip RDAP path
|
||||
if (!opts?.whoisOnly) {
|
||||
const bases = await getRdapBaseUrlsForTld(tld, opts);
|
||||
let bases = await getRdapBaseUrlsForTld(tld, opts);
|
||||
// Some ccTLD registries publish RDAP only at the registry TLD (e.g., br),
|
||||
// while the public suffix can be multi-label (e.g., com.br). Fallback to last label.
|
||||
if (bases.length === 0 && tld.includes(".")) {
|
||||
const registryTld = tld.split(".").pop() ?? tld;
|
||||
bases = await getRdapBaseUrlsForTld(registryTld, opts);
|
||||
}
|
||||
const tried: string[] = [];
|
||||
for (const base of bases) {
|
||||
tried.push(base);
|
||||
@@ -80,16 +90,28 @@ export async function lookupDomain(
|
||||
}
|
||||
|
||||
// Query the TLD server first; optionally follow registrar referrals (multi-hop)
|
||||
const res = await followWhoisReferrals(whoisServer, domain, opts);
|
||||
// Collect the chain and coalesce so we don't lose details when a registrar returns minimal/empty data.
|
||||
const chain = await collectWhoisReferralChain(whoisServer, domain, opts);
|
||||
if (chain.length === 0) {
|
||||
// Fallback to previous behavior as a safety net
|
||||
const res = await followWhoisReferrals(whoisServer, domain, opts);
|
||||
const record: DomainRecord = normalizeWhois(
|
||||
domain,
|
||||
tld,
|
||||
res.text,
|
||||
res.serverQueried,
|
||||
!!opts?.includeRaw,
|
||||
);
|
||||
return { ok: true, record };
|
||||
}
|
||||
|
||||
const record: DomainRecord = normalizeWhois(
|
||||
domain,
|
||||
tld,
|
||||
res.text,
|
||||
res.serverQueried,
|
||||
!!opts?.includeRaw,
|
||||
// Normalize all WHOIS texts in the chain and merge conservatively
|
||||
const normalizedRecords = chain.map((r) =>
|
||||
normalizeWhois(domain, tld, r.text, r.serverQueried, !!opts?.includeRaw),
|
||||
);
|
||||
return { ok: true, record };
|
||||
const [first, ...rest] = normalizedRecords;
|
||||
const mergedRecord = rest.length ? mergeWhoisRecords(first, rest) : first;
|
||||
return { ok: true, record: mergedRecord };
|
||||
} catch (err: unknown) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
return { ok: false, error: message };
|
||||
|
||||
Reference in New Issue
Block a user