diff --git a/lib/dispatcher/client.js b/lib/dispatcher/client.js index 705b43b88bd..15a2089839e 100644 --- a/lib/dispatcher/client.js +++ b/lib/dispatcher/client.js @@ -237,7 +237,7 @@ class Client extends DispatcherBase { throw new InvalidArgumentError('h2Options.settings.initialWindowSize must be a positive integer, greater than 0') } - if (h2Options.maxConcurrentStreams != null && (!Number.isInteger(h2Options.connectionWindowSize) || h2Options.maxConcurrentStreams < 1)) { + if (h2Options.maxConcurrentStreams != null && (!Number.isInteger(h2Options.maxConcurrentStreams) || h2Options.maxConcurrentStreams < 1)) { throw new InvalidArgumentError('h2Options.maxConcurrentStreams must be a positive integer, greater than 0') } @@ -331,7 +331,7 @@ class Client extends DispatcherBase { // especially on high-latency networks. This matches common production HTTP/2 servers. // - connectionWindowSize: 524288 (512KB) vs Node.js default (none set) // Provides better flow control for the entire connection across multiple streams. - initialWindowSize: h2Options?.initialWindowSize ?? initialWindowSize ?? 262144 + initialWindowSize: h2Options?.settings?.initialWindowSize ?? initialWindowSize ?? 262144 } } diff --git a/test/http2-options.js b/test/http2-options.js new file mode 100644 index 00000000000..0523227839b --- /dev/null +++ b/test/http2-options.js @@ -0,0 +1,44 @@ +'use strict' + +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') +const { Client } = require('..') +const { kHTTP2Options } = require('../lib/core/symbols') + +test('h2Options.maxConcurrentStreams is validated on its own value', async (t) => { + t = tspl(t, { plan: 4 }) + + const client = new Client('https://localhost', { + h2Options: { maxConcurrentStreams: 10 } + }) + t.strictEqual(client[kHTTP2Options].maxConcurrentStreams, 10) + await client.close() + + const withWindow = new Client('https://localhost', { + h2Options: { maxConcurrentStreams: 10, connectionWindowSize: 65535 } + }) + t.strictEqual(withWindow[kHTTP2Options].maxConcurrentStreams, 10) + await withWindow.close() + + t.throws(() => new Client('https://localhost', { + h2Options: { maxConcurrentStreams: 'not-a-number', connectionWindowSize: 65535 } + }), { code: 'UND_ERR_INVALID_ARG' }) + + t.throws(() => new Client('https://localhost', { + h2Options: { maxConcurrentStreams: 0 } + }), { code: 'UND_ERR_INVALID_ARG' }) +}) + +test('h2Options.settings.initialWindowSize reaches the session options', async (t) => { + t = tspl(t, { plan: 2 }) + + const client = new Client('https://localhost', { + h2Options: { settings: { initialWindowSize: 131072 } } + }) + t.strictEqual(client[kHTTP2Options].sessionOptions.initialWindowSize, 131072) + await client.close() + + const defaulted = new Client('https://localhost', { h2Options: {} }) + t.strictEqual(defaulted[kHTTP2Options].sessionOptions.initialWindowSize, 262144) + await defaulted.close() +})