Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!(H2): enable H2 by default #3814

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
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
15 changes: 12 additions & 3 deletions docs/docs/api/Client.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ Returns: `Client`

### Parameter: `ClientOptions`

> ⚠️ Warning: The `H2` support is experimental.

* **bodyTimeout** `number | null` (optional) - Default: `300e3` - The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Defaults to 300 seconds. Please note the `timeout` will be reset if you keep writing data to the socket everytime.
* **headersTimeout** `number | null` (optional) - Default: `300e3` - The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds.
* **keepAliveMaxTimeout** `number | null` (optional) - Default: `600e3` - The maximum allowed `keepAliveTimeout`, in milliseconds, when overridden by *keep-alive* hints from the server. Defaults to 10 minutes.
Expand All @@ -31,9 +29,20 @@ Returns: `Client`
* **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body.
* **autoSelectFamily**: `boolean` (optional) - Default: depends on local Node version, on Node 18.13.0 and above is `false`. Enables a family autodetection algorithm that loosely implements section 5 of [RFC 8305](https://tools.ietf.org/html/rfc8305#section-5). See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. This option is ignored if not supported by the current Node version.
* **autoSelectFamilyAttemptTimeout**: `number` - Default: depends on local Node version, on Node 18.13.0 and above is `250`. The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details.
* **allowH2**: `boolean` - Default: `false`. Enables support for H2 if the server has assigned bigger priority to it through ALPN negotiation.
* **allowH2**: `boolean` - Default: `true`. Enables support for H2 if the server has assigned bigger priority to it through ALPN negotiation.
* **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.

> **Notes about HTTP/2**
> - It only works under TLS connections. h2c is not supported.
> - The server must support HTTP/2 and choose it as the protocol during the ALPN negotiation.
> - The server must not have a bigger priority for HTTP/1.1 than HTTP/2.
> - Pseudo headers are automatically attached to the request. If you try to set them, they will be overwritten.
> - The `:path` header is automatically set to the request path.
> - The `:method` header is automatically set to the request method.
> - The `:scheme` header is automatically set to the request scheme.
> - The `:authority` header is automatically set to the request `host[:port]`.
> - `PUSH` frames are yet not supported.

#### Parameter: `ConnectOptions`

Every Tls option, see [here](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
Expand Down
2 changes: 1 addition & 1 deletion lib/core/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
const options = { path: socketPath, ...opts }
const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions)
timeout = timeout == null ? 10e3 : timeout
allowH2 = allowH2 != null ? allowH2 : false
allowH2 = allowH2 != null ? allowH2 : true
return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) {
let socket
if (protocol === 'https:') {
Expand Down
10 changes: 0 additions & 10 deletions lib/dispatcher/client-h2.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ const kOpenStreams = Symbol('open streams')

let extractBody

// Experimental
let h2ExperimentalWarned = false

/** @type {import('http2')} */
let http2
try {
Expand Down Expand Up @@ -82,13 +79,6 @@ function parseH2Headers (headers) {
async function connectH2 (client, socket) {
client[kSocket] = socket

if (!h2ExperimentalWarned) {
h2ExperimentalWarned = true
process.emitWarning('H2 support is experimental, expect them to change at any time.', {
code: 'UNDICI-H2'
})
}

const session = http2.connect(client[kUrl], {
createConnection: () => socket,
peerMaxConcurrentStreams: client[kMaxConcurrentStreams],
Expand Down
29 changes: 10 additions & 19 deletions test/fetch/http2.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ test('[Fetch] Issue#2311', async (t) => {
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

const response = await fetch(
Expand Down Expand Up @@ -91,8 +90,7 @@ test('[Fetch] Simple GET with h2', async (t) => {
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

const response = await fetch(
Expand Down Expand Up @@ -150,8 +148,7 @@ test('[Fetch] Should handle h2 request with body (string or buffer)', async (t)
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

const response = await fetch(
Expand Down Expand Up @@ -211,8 +208,7 @@ test(
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

t.after(closeClientAndServerAsPromise(client, server))
Expand Down Expand Up @@ -273,8 +269,7 @@ test('Should handle h2 request with body (Blob)', { skip: !Blob }, async (t) =>
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

t.after(closeClientAndServerAsPromise(client, server))
Expand Down Expand Up @@ -305,7 +300,7 @@ test('Should handle h2 request with body (Blob)', { skip: !Blob }, async (t) =>
test(
'Should handle h2 request with body (Blob:ArrayBuffer)',
{ skip: !Blob },
async (t) => {
async t => {
const server = createSecureServer(pem)
const expectedBody = 'hello'
const requestChunks = []
Expand Down Expand Up @@ -339,8 +334,7 @@ test(
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

t.after(closeClientAndServerAsPromise(client, server))
Expand Down Expand Up @@ -386,8 +380,7 @@ test('Issue#2415', async (t) => {
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

const response = await fetch(
Expand Down Expand Up @@ -438,8 +431,7 @@ test('Issue #2386', async (t) => {
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

t.after(closeClientAndServerAsPromise(client, server))
Expand Down Expand Up @@ -488,8 +480,7 @@ test('Issue #3046', async (t) => {
const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
}
})

t.after(closeClientAndServerAsPromise(client, server))
Expand Down
6 changes: 2 additions & 4 deletions test/http2-alpn.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) =>
connect: {
ca,
servername: 'agent1'
},
allowH2: true
}
})

// close the client on teardown
Expand Down Expand Up @@ -205,8 +204,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) =>
connect: {
ca,
servername: 'agent1'
},
allowH2: true
}
})

// close the client on teardown
Expand Down
Loading
Loading