-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Open
Labels
bugBug or defectBug or defect
Description
Runtime
node.js
Runtime version
22.17.1
Module version
21.4.3
Last module version without issue
No response
Used with
standalone
Any other relevant information
In HTTP2 the Host: header is no longer present. According to the spec:
In HTTP/2, the functionality of the HTTP/1.1 Host header is replaced by the :authority pseudo-header, which is a mandatory, colon-prefixed header that specifies the authority (host and port) of the target server. This change is part of HTTP/2's binary framing and header compression (HPACK), and any HTTP/2 request converted to HTTP/1.1 must create a Host header from the :authority pseudo-header.
- When building the request object and extracting its information (here), we rely solely on
Host:header. - Then, when starting Hapi in HTTP2 mode and performing a request, the
Host:header is missing, so the request.url getter) uses thehost:portfrom the _core.info. - Now, if the server is configured with an IPv6 host (such as
::1), the getter ends up building an invalid URL, as the host name is not surrounded by square brackets. An IPv6 address like2001:db8::1:8080would be ambiguous, as8080could be interpreted as the last segment of the IP address rather than the port.
What are you trying to achieve or the steps to reproduce?
Here are the steps to reproduce:
const fs = require('fs');
const { Server } = require('@hapi/hapi');
const http2 = require('http2');
// must use a valid certificate (self-signed ones don't work with HTTP2)
const key = fs.readFileSync('path/to/keyFile.key');
const cert = fs.readFileSync('path/to/certFile.crt');
const ca = fs.readFileSync('path/to/ca.crt');
const listener = http2.createSecureServer({
key,
cert,
ca,
});
const server = new Server({
host: '::1',
port: 10001,
listener,
tls: true,
});
server.route({
method: 'GET',
path: '/foo',
// Note that the handler is trying to print 'req.url' which triggers the getter logic
handler: (req, h) => h.response(`Hello world!: ${req.url}`),
});
server.start();
// Open your favorite browser and head over to: https://[::1]:10001/fooWhat was the result you got?
Debug: internal, implementation, error
TypeError: Invalid URL
at new URL (node:internal/url:818:25)
at Request._parseUrl (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/request.js:187:25)
at get url (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/request.js:121:21)
at handler (/home/gsoldevila/test/hapi.js:34:56)
at exports.Manager.execute (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/toolkit.js:57:29)
at internals.handler (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/handler.js:46:48)
at exports.execute (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/handler.js:31:36)
at Request._lifecycle (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/request.js:370:68)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async Request._execute (/home/gsoldevila/test/node_modules/@hapi/hapi/lib/request.js:280:9)
What result did you expect?
I would expect a 200 OK and seeing the following in my browser:
Hello world!: https://[::1]:10001/foo
Metadata
Metadata
Assignees
Labels
bugBug or defectBug or defect