Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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);
Expand Down Expand Up @@ -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();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could test if the req is an IPv6 request somehow, and choose Host or :authority accordingly. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would be great and expect if we want this included. I've done some light digging and come up with the following to help this along:

https://github.com/hapijs/hapi/blob/master/lib/core.js#L334 listens for whatever host / address you pass it, you can set it to loopback :: to bind to ipv6

Test it using builtins that only request IPv6

const http = require('http');

const options = {
    hostname: '::1', // The IPv6 loopback address of your local server
    port: 3000,
    path: '/',
    method: 'GET',
    family: 6 // Force IPv6
};

const req = http.request(options, (res) => {
    console.log(`STATUS: ${res.statusCode}`);
    res.setEncoding('utf8');
    res.on('data', (chunk) => {
        console.log(`BODY: ${chunk}`);
    });
});

req.on('error', (e) => {
    console.error(`problem with request: ${e.message}`);
});

req.end();

or alternatively, reuse some of the patterns in hapi tests: https://github.com/hapijs/hapi/blob/master/test/core.js#L925

The right place to add those tests would be https://github.com/hapijs/hapi/blob/master/test/core.js

Checkout some of the commentary around ipv6:

https://github.com/hapijs/hapi/blob/master/test/core.js#L102
https://github.com/hapijs/hapi/blob/master/test/core.js#L711

Seems like there's no explicit ipv6 tests, and they would need to be done only if the host machine has ipv6 enabled to prevent false positives.

Hope this helps!

@Marsup @kanongil anything to add or correct on the above?

const received = Date.now();

this.received = received;
Expand Down