fix(ext/node): http2 improvements — constants, error codes, settings, validation#33332
Conversation
- Implement sessionListenerAdded/sessionListenerRemoved to track remoteSettings and frameError listener counts in native fields bitfield - Remove duplicate process.nextTick for buffered data in constructor (setupHandle already handles this, having both risks double-processing) - Add maxOutstandingPings/maxOutstandingSettings validation and enforcement (defaults to 10, matching Node.js) - Initialize originSet via initOriginSet() for TLS h2 sessions in setupHandle - Define missing constants kSessionMaxInvalidFrames, kSessionMaxRejectedStreams, kSessionHasRemoteSettingsListeners Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t op All values in op_http2_constants were compile-time constants (nghttp2 C defines, literal strings, HTTP status codes). No reason to serialize them through serde/v8 at runtime. Move them to a JS constants module and import directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ERR_HTTP2_CONNECT_AUTHORITY, ERR_HTTP2_CONNECT_PATH, and ERR_HTTP2_CONNECT_SCHEME were defined as classes but never added to the `codes` object, causing "is not a constructor" at runtime. Also enables test-http2-connect-method.js and test-http2-connect.js in the node compat test suite. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use correct upper bound (2^31-1) for initialWindowSize validation per HTTP/2 spec (RFC 7540 Section 6.5.2) - Fix getUnpackedSettings to correctly handle TypedArray inputs by using Buffer.from(buf) which copies element values as bytes - Reject DataView in getUnpackedSettings (only Buffer/TypedArray valid) - Enable test-http2-getpackedsettings.js in compat suite Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Import missing error classes in http2.ts (ERR_HTTP2_INVALID_INFO_STATUS, ERR_HTTP2_STATUS_101, ERR_HTTP2_NESTED_PUSH, ERR_HTTP2_PING_CANCEL, ERR_HTTP2_SETTINGS_CANCEL, ERR_HTTP2_MAX_PENDING_SETTINGS_ACK, ERR_HTTP2_TRAILERS_ALREADY_SENT, ERR_HTTP2_TRAILERS_NOT_READY) - Register ERR_HTTP2_HEADER_SINGLE_VALUE, ERR_HTTP2_INVALID_CONNECTION_HEADERS, and ERR_HTTP2_INVALID_PSEUDOHEADER in the codes object - Enable test-http2-info-headers.js in compat suite Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…VALID_HTTP_TOKEN - Add static HideStackFramesError self-reference on ERR_HTTP2_INVALID_HEADER_VALUE, ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED, and ERR_INVALID_HTTP_TOKEN (needed by compat.js assertValidHeader which uses .HideStackFramesError pattern) - Register ERR_INVALID_HTTP_TOKEN in codes object - Fix compat.js to throw (not destroy) for invalid HTTP tokens in setHeader - Enable test-http2-invalidheaderfield.js and test-http2-invalidheaderfields-client.js in compat suite Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable test-http2-trailers.js and test-http2-util-assert-valid-pseudoheader.js in the compat suite. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d tokens Match Node.js behavior: use this.destroy() (not throw) for invalid HTTP tokens in kSetHeader/kAppendHeader. The assertValidHeader function already throws for names with spaces before this code path is reached. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add kStrictSingleValueFields symbol to Http2Session, defaulting to true (matching Node.js behavior). When set to false via session options, single-value header validation is skipped in buildNgHeaderString. Pass the option through all buildNgHeaderString call sites: sendTrailers, prepareResponseHeaders, processRespondWithFD, pushStream, additionalHeaders, prepareRequestHeadersArray, prepareRequestHeadersObject. Enables test-http2-single-headers-validation-disabled.js in compat suite. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
miracatbot
left a comment
There was a problem hiding this comment.
I think there is one behavioral issue to fix before this lands.
The new maxOutstandingPings check in Http2Session.ping() appears to reuse this[kState].pendingAck, but that same counter is also used by settings() / settingsCallback() for SETTINGS ACK tracking. That means a session with many outstanding SETTINGS ACKs can start rejecting ping() calls even when there are no outstanding PINGs.
In Node these limits are separate in effect: maxOutstandingSettings gates SETTINGS ACK pressure, while maxOutstandingPings applies to in-flight PINGs only. Reusing pendingAck here makes the ping throttling stricter than intended and couples two unrelated mechanisms.
Everything else I checked looked reasonable, but I’d fix that accounting before merging.
Node.js does not gate ping() calls with a pendingAck counter — that counter is only used for SETTINGS ACK tracking. The shared pendingAck counter meant outstanding SETTINGS ACKs could incorrectly reject ping() calls. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
miracatbot
left a comment
There was a problem hiding this comment.
Re-checked after the latest fix. The previously noted maxOutstandingPings / pendingAck coupling issue is resolved, and the remaining HTTP/2 compat changes look good to me.
Summary
op_http2_constantsRust op (all values are compile-time constants, no need for serde/v8 serialization)ERR_HTTP2_CONNECT_*,ERR_HTTP2_HEADER_SINGLE_VALUE,ERR_HTTP2_INVALID_CONNECTION_HEADERS,ERR_HTTP2_INVALID_PSEUDOHEADER,ERR_INVALID_HTTP_TOKENin thecodesobject; add missing imports inhttp2.tsHideStackFramesError— static self-reference onERR_HTTP2_INVALID_HEADER_VALUE,ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED,ERR_INVALID_HTTP_TOKEN(needed by compat.jsassertValidHeader)2^31-1upper bound forinitialWindowSize(per RFC 7540); fixgetUnpackedSettingsto handle TypedArray inputs correctly; reject DataViewstrictSingleValueFields— session option to disable single-value header validation, wired through allbuildNgHeaderStringcall sitesassertValidPseudoHeaderusage andthis.destroy()for invalid tokensNew compat tests enabled
test-http2-connect-method.jstest-http2-connect.jstest-http2-getpackedsettings.jstest-http2-info-headers.jstest-http2-invalidheaderfield.jstest-http2-invalidheaderfields-client.jstest-http2-misused-pseudoheaders.jstest-http2-single-headers-validation.jstest-http2-single-headers-validation-disabled.jstest-http2-trailers.jstest-http2-util-assert-valid-pseudoheader.jsTest plan
./x test-compatfor all newly enabled tests./x test-node http2passes./x test-spec node/http2passes./x lintand./x fmtpass🤖 Generated with Claude Code