diff --git a/lib/request.js b/lib/request.js index ffddd4aca..39e2dd4c2 100755 --- a/lib/request.js +++ b/lib/request.js @@ -183,8 +183,12 @@ exports = module.exports = internals.Request = class { this._normalizePath(url, options); return url; } + else { + + const host = this.info.host || this._formatIpv6Host(this._core.info.host, this._core.info.port); - this._url = new Url.URL(`${this._core.info.protocol}://${this.info.host || `${this._core.info.host}:${this._core.info.port}`}${source}`); + this._url = new Url.URL(`${this._core.info.protocol}://${host}${source}`); + } } else { @@ -201,6 +205,25 @@ exports = module.exports = internals.Request = class { return this._url; } + _isBareIpv6(host) { + + // If it's already bracketed, it's not a 'bare' IPv6 we need to wrap. + + if (host.startsWith('[') && host.endsWith(']')) { + return false; + } + + // An IPv6 address must contain at least two colons. + + const colonCount = (host.match(/:/g) || []).length; + return colonCount >= 2; + } + + _formatIpv6Host(host, port) { + + return this._isBareIpv6(host) ? `[${host}]:${port}`: `${host}:${port}`; + } + _normalizePath(url, options) { let path = this._core.router.normalize(url.pathname); @@ -624,7 +647,7 @@ internals.Info = class { this._request = request; const req = request.raw.req; - const host = req.headers.host ? req.headers.host.trim() : ''; + const host = (req.headers.host || req.headers[':authority'] || '').trim(); const received = Date.now(); this.received = received;