From 5057c6dd1a0988e1908db2ddd61bb970e81e970a Mon Sep 17 00:00:00 2001 From: K Date: Wed, 20 Sep 2023 17:03:10 +0000 Subject: [PATCH] feat(arns): add subdomain support Enables the arns feature to work when the node is hosted on a subdomain. Added to allow hosting on exiting domains. --- src/app.ts | 1 + src/middleware/arns.ts | 41 +++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/app.ts b/src/app.ts index 8514859c..32589ac7 100644 --- a/src/app.ts +++ b/src/app.ts @@ -83,6 +83,7 @@ if (config.ARNS_ROOT_HOST !== undefined) { app.use( createArnsMiddleware({ dataHandler, + rootHost: config.ARNS_ROOT_HOST, nameResolver: system.nameResolver, }), ); diff --git a/src/middleware/arns.ts b/src/middleware/arns.ts index bfa28e4e..2483f61b 100644 --- a/src/middleware/arns.ts +++ b/src/middleware/arns.ts @@ -25,33 +25,42 @@ const EXCLUDED_SUBDOMAINS = new Set('www'); export const createArnsMiddleware = ({ dataHandler, + rootHost, nameResolver, }: { dataHandler: Handler; + rootHost: string; nameResolver: NameResolver; }): Handler => asyncMiddleware(async (req, res, next) => { + const rootHostSubdomainLength = rootHost.split('.').length - 2; if ( - Array.isArray(req.subdomains) && - req.subdomains.length === 1 && - !EXCLUDED_SUBDOMAINS.has(req.subdomains[0]) && + // Ignore subdomains that are part of the ArNS root hostname. + !Array.isArray(req.subdomains) || + req.subdomains.length === rootHostSubdomainLength + ) { + next(); + return; + } + const arnsSubdomain = req.subdomains[req.subdomains.length - 1]; + if ( + EXCLUDED_SUBDOMAINS.has(arnsSubdomain) || // Avoid collisions with sandbox URLs by ensuring the subdomain length // is below the mininimum length of a sandbox subdomain. Undernames are // are an exception because they can be longer and '_' cannot appear in // base32. - (req.subdomains[0].length <= 48 || req.subdomains[0].match(/_/)) + (arnsSubdomain.length > 48 && !arnsSubdomain.match(/_/)) ) { - const { resolvedId, ttl } = await nameResolver.resolve(req.subdomains[0]); - if (resolvedId !== undefined) { - res.header('X-ArNS-Resolved-Id', resolvedId); - res.header('X-ArNS-TTL-Seconds', ttl.toString()); - res.header('Cache-Control', `public, max-age=${ttl}`); - dataHandler(req, res, next); - return; - } else { - sendNotFound(res); - return; - } + next(); + return; + } + const { resolvedId, ttl } = await nameResolver.resolve(arnsSubdomain); + if (resolvedId === undefined) { + sendNotFound(res); + return; } - next(); + res.header('X-ArNS-Resolved-Id', resolvedId); + res.header('X-ArNS-TTL-Seconds', ttl.toString()); + res.header('Cache-Control', `public, max-age=${ttl}`); + dataHandler(req, res, next); });