diff --git a/lib/url.js b/lib/url.js index 50126ae9bfc4d0..319050ca1530e5 100644 --- a/lib/url.js +++ b/lib/url.js @@ -45,6 +45,15 @@ const unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims); // Allowed by RFCs, but cause of XSS attacks. Always escape these. const autoEscape = ['\''].concat(unwise); + +const slashPattern = /\\/g; + +const userAtHostPattern = /^\/\/[^@\/]+@[^@\/]+/; + +const colonPattern = /%3A/i; + +const pathnameEscapePattern = /[?#]/g; + // Characters that are never ever allowed in a hostname. // Note that any invalid chars are also handled, but these // are the ones that are *expected* to be seen, so we fast-path them. @@ -97,9 +106,9 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { var queryIndex = url.indexOf('?'), splitter = (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', - uSplit = url.split(splitter), - slashRegex = /\\/g; - uSplit[0] = uSplit[0].replace(slashRegex, '/'); + uSplit = url.split(splitter); + + uSplit[0] = uSplit[0].replace(slashPattern, '/'); url = uSplit.join(splitter); var rest = url; @@ -142,7 +151,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + if (slashesDenoteHost || proto || rest.match(userAtHostPattern)) { var slashes = rest.substr(0, 2) === '//'; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.substr(2); @@ -362,7 +371,7 @@ Url.prototype.format = function() { var auth = this.auth || ''; if (auth) { auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); + auth = auth.replace(colonPattern, ':'); auth += '@'; } @@ -406,7 +415,7 @@ Url.prototype.format = function() { if (hash && hash.charAt(0) !== '#') hash = '#' + hash; if (search && search.charAt(0) !== '?') search = '?' + search; - pathname = pathname.replace(/[?#]/g, function(match) { + pathname = pathname.replace(pathnameEscapePattern, function(match) { return encodeURIComponent(match); }); search = search.replace('#', '%23');