From 199a66a35796d740cb9280682bb6e87171c7b115 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 26 Jan 2026 11:11:17 -0500 Subject: [PATCH 1/3] feat: use new URL instead of url.parse --- lib/Server.js | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index bbfe8aa29d..19a55f3bf3 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -3050,6 +3050,27 @@ class Server { return false; } + /** + * Extracts and normalizes the hostname from a header, removing brackets for IPv6. + * @param {string} header header value + * @returns {string|null} hostname or null + */ + #parseHostnameFromHeader = function (header) { + if (!header) return null; + try { + // If the header does not have a scheme, prepend // so URL can parse it + const url = new URL(/^(.+:)?\/\//.test(header) ? header : `//${header}`); + let hostname = url.hostname; + // Normalize IPv6: remove brackets if present + if (hostname.startsWith("[") && hostname.endsWith("]")) { + hostname = hostname.slice(1, -1); + } + return hostname; + } catch { + return null; + } + }; + /** * @private * @param {{ [key: string]: string | undefined }} headers headers @@ -3074,15 +3095,7 @@ class Server { return true; } - // use the node url-parser to retrieve the hostname from the host-header. - // TODO resolve me in the next major release - // eslint-disable-next-line n/no-deprecated-api - const { hostname } = url.parse( - // if header doesn't have scheme, add // for parsing. - /^(.+:)?\/\//.test(header) ? header : `//${header}`, - false, - true, - ); + const hostname = this.#parseHostnameFromHeader(header); if (hostname === null) { return false; @@ -3096,8 +3109,7 @@ class Server { // A note on IPv6 addresses: // header will always contain the brackets denoting // an IPv6-address in URLs, - // these are removed from the hostname in url.parse(), - // so we have the pure IPv6-address in hostname. + // these aren't removed from the hostname in new URL(), // For convenience, always allow localhost (hostname === 'localhost') // and its subdomains (hostname.endsWith(".localhost")). // allow hostname of listening address (hostname === this.options.host) @@ -3132,9 +3144,7 @@ class Server { return true; } - // TODO resolve me in the next major release - // eslint-disable-next-line n/no-deprecated-api - const origin = url.parse(originHeader, false, true).hostname; + const origin = this.#parseHostnameFromHeader(originHeader); if (origin === null) { return false; @@ -3154,13 +3164,7 @@ class Server { return true; } - // eslint-disable-next-line n/no-deprecated-api - const host = url.parse( - // if hostHeader doesn't have scheme, add // for parsing. - /^(.+:)?\/\//.test(hostHeader) ? hostHeader : `//${hostHeader}`, - false, - true, - ).hostname; + const host = this.#parseHostnameFromHeader(hostHeader); if (host === null) { return false; From 7e9fc7c15be04dc7e668acc53708ef549e62f035 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 26 Jan 2026 11:36:22 -0500 Subject: [PATCH 2/3] feat: add private class field to Server class --- types/lib/Server.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/types/lib/Server.d.ts b/types/lib/Server.d.ts index 9ad8a3dca8..5ba932ce6e 100644 --- a/types/lib/Server.d.ts +++ b/types/lib/Server.d.ts @@ -1409,6 +1409,7 @@ declare class Server< * @param {((err?: Error) => void)=} callback callback */ stopCallback(callback?: ((err?: Error) => void) | undefined): void; + #private; } declare namespace Server { export { From 0dfbd6c06b70fb03cfe190490ec55f2562c56819 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Fri, 30 Jan 2026 16:44:41 -0500 Subject: [PATCH 3/3] feat: update hostname parsing to use with default base --- lib/Server.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 19a55f3bf3..c47026ca84 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -3059,12 +3059,17 @@ class Server { if (!header) return null; try { // If the header does not have a scheme, prepend // so URL can parse it - const url = new URL(/^(.+:)?\/\//.test(header) ? header : `//${header}`); - let hostname = url.hostname; + const parseUrl = new URL( + /^(.+:)?\/\//.test(header) ? header : `//${header}`, + "http://localhost/", + ); + + let hostname = parseUrl.hostname; // Normalize IPv6: remove brackets if present if (hostname.startsWith("[") && hostname.endsWith("]")) { hostname = hostname.slice(1, -1); } + return hostname; } catch { return null;