From 1086468aa3d328d2eac00bf66058906553ecd209 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 2 Dec 2021 09:58:05 -0800 Subject: [PATCH] url: detect hostname more reliably in url.parse() Based on existing tests and code comments, url.parse() is expected to treat any URL containing user@host as having a hostname. However, it turns out this behavior relies on the URL having a hash which is surprising, to put it mildly. Detect the host even without the hash. PR-URL: https://github.com/nodejs/node/pull/41031 Reviewed-By: Ruben Bridgewater Reviewed-By: Myles Borins --- lib/url.js | 6 ++++- test/parallel/test-url-parse-format.js | 32 +++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/url.js b/lib/url.js index 93ad447b626903..745c7c9930deda 100644 --- a/lib/url.js +++ b/lib/url.js @@ -187,6 +187,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // Back slashes before the query string get converted to forward slashes // See: https://code.google.com/p/chromium/issues/detail?id=25916 let hasHash = false; + let hasAt = false; let start = -1; let end = -1; let rest = ''; @@ -219,6 +220,9 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // Only convert backslashes while we haven't seen a split character if (!split) { switch (code) { + case CHAR_AT: + hasAt = true; + break; case CHAR_HASH: hasHash = true; // Fall through @@ -259,7 +263,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { } } - if (!slashesDenoteHost && !hasHash) { + if (!slashesDenoteHost && !hasHash && !hasAt) { // Try fast path regexp const simplePath = simplePathPattern.exec(rest); if (simplePath) { diff --git a/test/parallel/test-url-parse-format.js b/test/parallel/test-url-parse-format.js index cbfc58b1123a72..4fce198624a6fc 100644 --- a/test/parallel/test-url-parse-format.js +++ b/test/parallel/test-url-parse-format.js @@ -946,7 +946,37 @@ const parseTests = { pathname: '/', path: '/', href: 'wss://www.example.com/' - } + }, + + '//fhqwhgads@example.com/everybody-to-the-limit': { + protocol: null, + slashes: true, + auth: 'fhqwhgads', + host: 'example.com', + port: null, + hostname: 'example.com', + hash: null, + search: null, + query: null, + pathname: '/everybody-to-the-limit', + path: '/everybody-to-the-limit', + href: '//fhqwhgads@example.com/everybody-to-the-limit' + }, + + '//fhqwhgads@example.com/everybody#to-the-limit': { + protocol: null, + slashes: true, + auth: 'fhqwhgads', + host: 'example.com', + port: null, + hostname: 'example.com', + hash: '#to-the-limit', + search: null, + query: null, + pathname: '/everybody', + path: '/everybody', + href: '//fhqwhgads@example.com/everybody#to-the-limit' + }, }; for (const u in parseTests) {