Skip to content

fix(ext/node): wire http2 maxSettings option to nghttp2_option_set_max_settings#33790

Merged
littledivy merged 3 commits into
denoland:mainfrom
divybot:claude/test-http2-max-settings
May 3, 2026
Merged

fix(ext/node): wire http2 maxSettings option to nghttp2_option_set_max_settings#33790
littledivy merged 3 commits into
denoland:mainfrom
divybot:claude/test-http2-max-settings

Conversation

@divybot

@divybot divybot commented May 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Enables test-http2-max-settings in node_compat suite.

Test plan

  • cargo test --test node_compat -- test-http2-max-settings

divybot and others added 3 commits April 29, 2026 10:43
…x_settings

The `maxSettings` server option (limit on SETTINGS entries per frame, with
connection-error response when exceeded) was not wired up. The Rust code
was instead routing `maxOutstandingSettings` (a Node.js-internal queue
limit for outbound SETTINGS awaiting ACK, with no nghttp2 equivalent) to
`nghttp2_option_set_max_settings`, so the server accepted the default 32
entries regardless of the user-supplied `maxSettings`.

Read `OptionsIndex::MaxSettings` (index 9) and pass it to nghttp2; drop
the wrong call for `MaxOutstandingSettings`. Enables
parallel/test-http2-max-settings.js.

Co-authored-by: Divy Srivastava <[email protected]>
…x_settings

Enables tests/node_compat/runner/suite/test/parallel/test-http2-max-settings.js

Co-authored-by: Divy Srivastava <[email protected]>

@fibibot fibibot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM. Tight semantic-correction fix. The previous code was conflating two distinct Node.js HTTP/2 options:

  • maxOutstandingSettings (buffer[7]) — Node-internal queue limit for outbound SETTINGS frames awaiting peer ACK. nghttp2 has no equivalent.
  • maxSettings (buffer[9]) — limit on inbound SETTINGS entries per frame, which is exactly what nghttp2_option_set_max_settings controls.

Old code: nghttp2_option_set_max_settings(options, max_outstanding_settings) — wrong semantics, would silently cap inbound SETTINGS entries to whatever the user passed for maxOutstandingSettings.

New code: nghttp2_option_set_max_settings(options, max_settings) reading from the correct buffer slot, plus an explanatory comment that maxOutstandingSettings is intentionally not mapped to any nghttp2 option (it's a JS-side concern handled via kMaxOutstandingSettings symbol + kState.pendingAck check at http2.ts:3344).

What I checked

  • JS side already wires options.maxSettings to optionsBuffer[IDX_OPTIONS_MAX_SETTINGS] at internal/http2/util.ts:283 (MathMax(1, options.maxSettings)), so the buffer slot was already populated; the Rust side was just reading the wrong slot.
  • MaxSettings = 9 is defined in ext/node/ops/http2/types.rs:71, matches the JS IDX_OPTIONS_MAX_SETTINGS = 9. ✓
  • maxOutstandingSettings JS handling unchanged: still tracked via the kMaxOutstandingSettings symbol in http2.ts:3090,3344 and gates pendingAck count on the polyfill side. The Rust code just stops trying to map it to an nghttp2 option that doesn't exist.

Behavior change to flag

This is a backwards-incompat fix for any user who was relying on the old (buggy) mapping — passing maxOutstandingSettings: N would previously cap nghttp2's inbound-SETTINGS-entries limit to N. After this PR, users need to pass maxSettings: N for that effect. Since the old behavior was semantically wrong (and not what Node does), this is the right direction.

CI

132/135 success, 1 pending (wpt release linux-x86_64 — orthogonal to ext/node http2), 2 skip, 0 fail. The new parallel/test-http2-max-settings.js passes across all platforms.

@littledivy
littledivy merged commit 60b234f into denoland:main May 3, 2026
136 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants