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 <ruben@bridgewater.de>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
This commit is contained in:
Rich Trott 2021-12-02 09:58:05 -08:00 committed by GitHub
parent 9e0fb1acef
commit 1086468aa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 2 deletions

View File

@ -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) {

View File

@ -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) {