Fix DuckDNS double-suffixing a subdomain that already includes .duckdns.org (#128)

Reported error when adding a DuckDNS provider with
subdomains="nl-theta42.duckdns.org" (the full name, as DuckDNS's own
site displays it):

  {"name": "EntryNotFound", "message": "Domain:duckdns.org does not exists"}

listDomains() blindly appended ".duckdns.org" to whatever was entered,
turning "nl-theta42.duckdns.org" into
"nl-theta42.duckdns.org.duckdns.org". tld-extract doesn't know
duckdns.org is a shared suffix, so it parsed that malformed string
down to domain "duckdns.org" — surfacing as a confusing EntryNotFound
two layers away from the actual cause (Domain.create's internal
lookup).

Add __normalizeLabel() to strip a trailing ".duckdns.org" (and
lowercase) before use, so both "myhost" and "myhost.duckdns.org" work
identically. Also make __label()'s existing suffix-strip
case-insensitive to match.
This commit is contained in:
2026-07-14 12:29:06 -04:00
committed by GitHub
parent 1c7ad9aaae
commit e091c15d95
2 changed files with 33 additions and 2 deletions
@@ -200,6 +200,25 @@ describe('DNS Provider Contract Compliance', () => {
const instance = new DuckDns({token: 'mock-token', subdomains: 'mockhost'});
assert.strictEqual(instance.__label({domain: 'mockhost.duckdns.org'}), 'mockhost');
});
test('__normalizeLabel accepts both the bare label and the full duckdns.org name', () => {
const instance = new DuckDns({token: 'mock-token', subdomains: 'mockhost'});
assert.strictEqual(instance.__normalizeLabel('mockhost'), 'mockhost');
assert.strictEqual(instance.__normalizeLabel('mockhost.duckdns.org'), 'mockhost');
assert.strictEqual(instance.__normalizeLabel('MockHost.DuckDNS.org'), 'mockhost');
});
test('listDomains does not double-suffix a subdomains value that already includes .duckdns.org', async () => {
const instance = new DuckDns({token: 'mock-token', subdomains: 'nl-theta42.duckdns.org,other'});
// Stub out the network call — this test is only about what domain
// name(s) listDomains() builds from `subdomains`, not the live API.
instance.update = async () => {};
const domains = await instance.listDomains();
assert.deepStrictEqual(domains, [
{domain: 'nl-theta42.duckdns.org'},
{domain: 'other.duckdns.org'},
]);
});
});
});