Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
9383d83
http: honor --insecure-http-parser, freeze writeHead framing, drop ov…
cirospaciari Jul 17, 2026
69fc04f
Merge remote-tracking branch 'origin/main' into ciro/node-http-v26-co…
cirospaciari Jul 17, 2026
c5a99f8
http: fix framing/leniency edge cases found in review
cirospaciari Jul 17, 2026
df4965e
http: run a connectionListener so emit('connection', socket) is served
cirospaciari Jul 17, 2026
7cf0e01
http2: serve the HTTP/1 half of protocol autoselection
cirospaciari Jul 17, 2026
7540792
http: bound request headers the way llhttp does
cirospaciari Jul 17, 2026
e800d5d
http: render the chunked Transfer-Encoding after Connection, like Node
cirospaciari Jul 17, 2026
1d5e39f
test: the 200 after a 304 is chunked, like Node
cirospaciari Jul 17, 2026
013e52f
http: honor the chunked Transfer-Encoding bit in the JS fallback
cirospaciari Jul 17, 2026
11588aa
Merge branch 'main' into ciro/node-http-v26-compat
cirospaciari Jul 17, 2026
a733f96
http: charge a header value's trailing whitespace, like llhttp
cirospaciari Jul 17, 2026
65377b9
Merge remote-tracking branch 'origin/ciro/node-http-v26-compat' into …
cirospaciari Jul 17, 2026
d0c0354
http: split parser leniency into llhttp's two bits
cirospaciari Jul 17, 2026
ac379e9
http: honor the auto-header bits exactly in the JS fallback
cirospaciari Jul 17, 2026
4371163
http: bound pipelined dispatch like Node's flood prevention
cirospaciari Jul 17, 2026
a91f521
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 17, 2026
b8b6be5
http: hand off Upgrade and CONNECT in the JS fallback
cirospaciari Jul 17, 2026
d9a4921
Merge remote-tracking branch 'origin/ciro/node-http-v26-compat' into …
cirospaciari Jul 17, 2026
09c0380
test: cover the fallback's Upgrade/CONNECT handoff
cirospaciari Jul 17, 2026
6e654b4
Merge branch 'main' into ciro/node-http-v26-compat
cirospaciari Jul 17, 2026
ce59cfe
address review: CONNECT double-delivery, spill-replay backpressure, f…
robobun Jul 17, 2026
a76d5a8
Merge branch 'main' into ciro/node-http-v26-compat; address ce59cfe r…
robobun Jul 17, 2026
6641668
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 17, 2026
363c67c
http2: fail the session when an outbound header block cannot be encoded
cirospaciari Jul 17, 2026
73065c5
http2: perf_hooks entries, END_STREAM on the final DATA frame, and cl…
cirospaciari Jul 17, 2026
b38891c
http2: pack END_STREAM onto end(chunk) and match node's frame accounting
cirospaciari Jul 17, 2026
958112f
http2: fix silent client stall when the socket flows before connect c…
cirospaciari Jul 17, 2026
f4a9f71
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 17, 2026
05ed257
h2: release auto-flush registration after deferred COMPRESSION_ERROR;…
robobun Jul 17, 2026
754d353
ci: retrigger
robobun Jul 18, 2026
9dd71e1
h2: keep pending_header_compression_error latched across the onError …
robobun Jul 18, 2026
3a54f48
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 18, 2026
4ce300b
fallback: add writeInformational so writeEarlyHints/writeProcessing r…
robobun Jul 18, 2026
be93d72
h2/fallback review: send_trailers encode failure -> session COMPRESSI…
robobun Jul 18, 2026
cb56096
test: wire must-not-run request handlers to reject/flag instead of th…
robobun Jul 18, 2026
6d0f17b
revert send_trailers to per-stream FRAME_SIZE_ERROR; fix onHttp1Socke…
robobun Jul 18, 2026
a227e00
Merge branch 'main' into ciro/node-http-v26-compat
cirospaciari Jul 20, 2026
8715a0e
Merge branch 'main' into ciro/node-http-v26-compat
robobun Jul 22, 2026
d361c02
docs: move rewrite_read doc comment back above its fn (sync_engine_fr…
robobun Jul 22, 2026
f641f77
fallback: map HPE_CHUNK_EXTENSIONS_OVERFLOW to 413 like Node's socket…
robobun Jul 22, 2026
9ac1cf6
Merge branch 'main' into ciro/node-http-v26-compat
cirospaciari Jul 22, 2026
77cbe93
http2: defer streamEnd(7) destroy when end(chunk)'s own _write drove …
robobun Jul 22, 2026
3c6783e
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 22, 2026
4485e5c
http2: stamp timeToFirstHeader in server streamHeaders too; fallback …
robobun Jul 22, 2026
1af5840
Merge branch 'main' into ciro/node-http-v26-compat
cirospaciari Jul 23, 2026
fe85cfb
Merge remote-tracking branch 'origin/main' into ciro/node-http-v26-co…
robobun Aug 3, 2026
4227bbf
NodeHTTP.cpp: hoist lenientHttpFlags.toInt32 and exception-check befo…
robobun Aug 3, 2026
b87e396
trim comments to <=3 lines, cite spec/node source
robobun Aug 3, 2026
b85baf4
test(spawn-maxbuf): widen killWindow on ASAN builds too
robobun Aug 4, 2026
29b0954
Merge remote-tracking branch 'origin/main' into ciro/node-http-v26-co…
robobun Aug 4, 2026
9a12c62
Merge remote-tracking branch 'origin/main' into ciro/node-http-v26-co…
robobun Aug 4, 2026
64bcf70
node:http flood prevention: rename nodeHttpReadsPausedSignal -> nodeH…
robobun Aug 4, 2026
59c93f1
http2.ts: drop unused throwNotImplemented import and unused bunTLSCon…
robobun Aug 4, 2026
86d0bda
node:http flood prevention: hold the parked-request spill in a WTF::V…
robobun Aug 4, 2026
70833a7
http2: mark the push stream handed out on the unencodable-block path …
robobun Aug 4, 2026
e758733
test: restore node-http-proxy.js to its original localhost form
robobun Aug 4, 2026
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
7 changes: 5 additions & 2 deletions packages/bun-uws/src/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -772,10 +772,13 @@ struct TemplatedApp {
return std::move(*this);
}

TemplatedApp &&setFlags(bool requireHostHeader, bool useStrictMethodValidation, bool useInsecureHTTPParser, bool httpAllowHalfOpen) {
/* lenientHttpFlags: bit 0 = lenient header values (llhttp LENIENT_HEADERS),
* bit 1 = lenient transfer-encoding (llhttp LENIENT_TRANSFER_ENCODING). */
TemplatedApp &&setFlags(bool requireHostHeader, bool useStrictMethodValidation, uint8_t lenientHttpFlags, bool httpAllowHalfOpen) {
httpContext->getSocketContextData()->flags.requireHostHeader = requireHostHeader;
httpContext->getSocketContextData()->flags.useStrictMethodValidation = useStrictMethodValidation;
httpContext->getSocketContextData()->flags.useInsecureHTTPParser = useInsecureHTTPParser;
httpContext->getSocketContextData()->flags.useInsecureHTTPParser = (lenientHttpFlags & 1) != 0;
httpContext->getSocketContextData()->flags.useLenientTransferEncoding = (lenientHttpFlags & 2) != 0;
httpContext->getSocketContextData()->flags.httpAllowHalfOpen = httpAllowHalfOpen;
return std::move(*this);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/bun-uws/src/HttpContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ struct HttpContext {
nodeHttpChunkedExtensionsByteCount = &nodeHttpResponseData->chunkedExtensionsByteCount;
}

auto result = httpResponseData->template consumePostPadded<IsNodeHttp>(httpContextData->maxHeaderSize, httpResponseData->isConnectRequest, httpContextData->flags.requireHostHeader,httpContextData->flags.useStrictMethodValidation, httpContextData->flags.useInsecureHTTPParser, nodeHttpRequestTrailers, nodeHttpChunkedExtensionsByteCount, data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {
auto result = httpResponseData->template consumePostPadded<IsNodeHttp>(httpContextData->maxHeaderSize, httpResponseData->isConnectRequest, httpContextData->flags.requireHostHeader,httpContextData->flags.useStrictMethodValidation, httpContextData->flags.useInsecureHTTPParser, httpContextData->flags.useLenientTransferEncoding, nodeHttpRequestTrailers, nodeHttpChunkedExtensionsByteCount, data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {


/* For every request we reset the timeout and hang until user makes action */
Expand Down
15 changes: 10 additions & 5 deletions packages/bun-uws/src/HttpContextData.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,17 @@ struct HttpFlags {
bool requireHostHeader: 1 = true;
bool isAuthorized: 1 = false;
bool useStrictMethodValidation: 1 = false;
/* node:http insecureHTTPParser server option. NOTE: unlike Node's server
* (which fans kLenientAll out to all 10 llhttp lenient setters), the uWS
* parser only implements the LENIENT_HEADERS bit (control bytes accepted
* in field values); TE+CL conflict, chunked-size/CRLF strictness, version
* and header-token checks are still enforced. */
/* node:http parser leniency. Two of llhttp's lenient bits are implemented:
* useInsecureHTTPParser is LENIENT_HEADERS (control bytes accepted in field
* values) — set for both httpValidation "relaxed" and "insecure" —
* and useLenientTransferEncoding is LENIENT_TRANSFER_ENCODING (a chunked
* coding with another value after it, e.g. a duplicate Transfer-Encoding:
* chunked header, is accepted) — set only for "insecure" /
* --insecure-http-parser, never for "relaxed", which must relax header
* values alone. The TE+CL conflict, chunked-size/CRLF strictness, version
* and header-token checks are still enforced under both. */
bool useInsecureHTTPParser: 1 = false;
bool useLenientTransferEncoding: 1 = false;
/* node:http server.httpAllowHalfOpen: when true, a peer FIN with in-flight
* or queued responses keeps the connection open until they drain (Node's
* socketOnEnd); when false (the default), the connection ends right away. */
Expand Down
70 changes: 59 additions & 11 deletions packages/bun-uws/src/HttpParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,14 @@ struct HttpResponseData;
bool nodeHttpSawConnectionClose = false;

const size_t MAX_FALLBACK_SIZE = BUN_DEFAULT_MAX_HTTP_HEADER_SIZE;
/* maxHeaderSize bounds what llhttp counts — the URL plus each field name and
* value — but the raw block also carries framing llhttp never charges: the
* method and " HTTP/1.1\r\n", a ": " and "\r\n" per header, and the terminating
* "\r\n". Bounding raw bytes by maxHeaderSize itself would reject a request
* Node accepts, so the raw bounds get exactly that framing as slack. It stays
* finite: at most UWS_HTTP_MAX_HEADERS_COUNT headers contribute 4 bytes each,
* and a field value's raw span is already bounded by the in-loop check. */
static constexpr size_t MAX_HEADER_FRAMING_SLACK = UWS_HTTP_MAX_HEADERS_COUNT * 4 + 64;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

/* Maximum size of the chunk extensions of a single chunk, matching Node's
* kMaxChunkExtensionsSize in src/node_http_parser.cc (16 KiB). Enforced
Expand Down Expand Up @@ -938,8 +946,18 @@ struct HttpResponseData;
if(requestLineResult.isConnect) {
isConnectRequest = true;
}
/* No request headers found */
const char * headerStart = (headers[0].key.length() > 0) ? headers[0].key.data() : end;
/* llhttp — and therefore Node — bounds the header block by the bytes it hands
* to its callbacks: on_url, then each field name and field value. It does not
* charge the method, " HTTP/1.1\r\n", the ": " separators or the "\r\n" line
* endings against that budget, so counting the raw offset into the buffer
* rejects requests Node accepts. Mirror llhttp's TrackHeader: accumulate
* name + value lengths and fail once the total reaches maxHeaderSize. The
* fallback buffer keeps its own bound (maxBufferedHeaderSize below), which is
* what caps how much raw data a fragmented request may buffer. */
uint64_t headerNread = headers[0].value.length();
if (maxHeaderSize && headerNread >= maxHeaderSize) {
return HttpParserResult::error(HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, HTTP_PARSER_ERROR_REQUEST_HEADER_FIELDS_TOO_LARGE);
}

/* Check if we can see if headers follow or not */
if (postPaddedBuffer + 2 > end) {
Expand All @@ -961,7 +979,8 @@ struct HttpResponseData;
preliminaryKey = postPaddedBuffer;
postPaddedBuffer = consumeFieldName(postPaddedBuffer);
headers->key = std::string_view(preliminaryKey, (size_t) (postPaddedBuffer - preliminaryKey));
if(maxHeaderSize && (uintptr_t)(postPaddedBuffer - headerStart) > maxHeaderSize) {
headerNread += headers->key.length();
if(maxHeaderSize && headerNread >= maxHeaderSize) {
return HttpParserResult::error(HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, HTTP_PARSER_ERROR_REQUEST_HEADER_FIELDS_TOO_LARGE);
}
/* We should not accept whitespace between key and colon, so colon must foloow immediately */
Expand Down Expand Up @@ -1004,7 +1023,16 @@ struct HttpResponseData;
}
break;
}
if(maxHeaderSize && (uintptr_t)(postPaddedBuffer - headerStart) > maxHeaderSize) {
/* Bound the value before its terminator is found — a value that never
* terminates must still overflow here, exactly where llhttp would, or an
* oversized unterminated header just waits for more data instead of
* failing. llhttp is handed the value with leading OWS already skipped,
* so that OWS is not charged. */
const char *countedValueStart = preliminaryValue;
while (countedValueStart < postPaddedBuffer && isHTTPHeaderValueWhitespace((unsigned char) *countedValueStart)) {
countedValueStart++;
}
if(maxHeaderSize && headerNread + (uintptr_t)(postPaddedBuffer - countedValueStart) >= maxHeaderSize) {
return HttpParserResult::error(HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, HTTP_PARSER_ERROR_REQUEST_HEADER_FIELDS_TOO_LARGE);
}
if (end - postPaddedBuffer < 2) {
Expand All @@ -1015,6 +1043,15 @@ struct HttpResponseData;
if (postPaddedBuffer[1] == '\n') {
/* Store this header, it is valid */
headers->value = std::string_view(preliminaryValue, (size_t) (postPaddedBuffer - preliminaryValue));
/* Charge the value the way llhttp hands it to on_header_value: leading
* OWS skipped, trailing OWS still counted. Measure before the trims
* below, or a value padded with trailing spaces is undercharged and we
* accept a header block Node answers with 431. */
const char *chargedValueStart = preliminaryValue;
while (chargedValueStart < postPaddedBuffer && isHTTPHeaderValueWhitespace((unsigned char) *chargedValueStart)) {
chargedValueStart++;
}
const size_t chargedValueLength = (size_t) (postPaddedBuffer - chargedValueStart);
Comment thread
robobun marked this conversation as resolved.
Outdated
postPaddedBuffer += 2;
/* Trim trailing whitespace (SP, HTAB) per RFC 9110 Section 5.5 */
while (headers->value.length() && isHTTPHeaderValueWhitespace(headers->value.back())) {
Expand All @@ -1026,7 +1063,8 @@ struct HttpResponseData;
headers->value.remove_prefix(1);
}

if(maxHeaderSize && (uintptr_t)(postPaddedBuffer - headerStart) > maxHeaderSize) {
headerNread += chargedValueLength;
if(maxHeaderSize && headerNread >= maxHeaderSize) {
return HttpParserResult::error(HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, HTTP_PARSER_ERROR_REQUEST_HEADER_FIELDS_TOO_LARGE);
}
headers++;
Expand Down Expand Up @@ -1062,7 +1100,7 @@ struct HttpResponseData;

/* This is the only caller of getHeaders and is thus the deepest part of the parser. */
template <bool ConsumeMinimally, bool IsNodeHttp>
HttpParserResult fenceAndConsumePostPadded(uint64_t maxHeaderSize, bool& isConnectRequest, bool requireHostHeader, bool useStrictMethodValidation, bool useInsecureHTTPParser, std::string *nodeHttpRequestTrailers, uint64_t *chunkedExtensionsByteCount, char *data, unsigned int length, void *user, void *reserved, HttpRequest *req, MoveOnlyFunction<void *(void *, HttpRequest *)> &requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &dataHandler) {
HttpParserResult fenceAndConsumePostPadded(uint64_t maxHeaderSize, bool& isConnectRequest, bool requireHostHeader, bool useStrictMethodValidation, bool useInsecureHTTPParser, bool useLenientTransferEncoding, std::string *nodeHttpRequestTrailers, uint64_t *chunkedExtensionsByteCount, char *data, unsigned int length, void *user, void *reserved, HttpRequest *req, MoveOnlyFunction<void *(void *, HttpRequest *)> &requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &dataHandler) {

/* How much data we CONSUMED (to throw away) */
unsigned int consumedTotal = 0;
Expand Down Expand Up @@ -1118,7 +1156,7 @@ struct HttpResponseData;
consumedTotal += consumed;

/* Even if we could parse it, check for length here as well */
const uint64_t maxBufferedHeaderSize = maxHeaderSize ? maxHeaderSize : MAX_FALLBACK_SIZE;
const uint64_t maxBufferedHeaderSize = maxHeaderSize ? (maxHeaderSize + MAX_HEADER_FRAMING_SLACK) : MAX_FALLBACK_SIZE;
if (consumed > maxBufferedHeaderSize) {
return HttpParserResult::error(HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE, HTTP_PARSER_ERROR_REQUEST_HEADER_FIELDS_TOO_LARGE);
}
Expand Down Expand Up @@ -1180,6 +1218,16 @@ struct HttpResponseData;
bool deferredTransferEncodingError = IsNodeHttp && transferEncoding.has
&& !transferEncoding.invalid && !transferEncoding.chunked && !contentLengthStringLen;

/* llhttp's LENIENT_TRANSFER_ENCODING (part of Node's kLenientAll — the
* insecureHTTPParser / httpValidation: "insecure" surface, never
* "relaxed") accepts a chunked coding with another value after it,
* e.g. a duplicate Transfer-Encoding: chunked header. It does not
* relax the Transfer-Encoding + Content-Length conflict, so only the
* coding-shape verdict is cleared; the conflicts folded in below
* still reject. */
if (useLenientTransferEncoding) {
transferEncoding.invalid = false;
}
transferEncoding.invalid = transferEncoding.invalid || (transferEncoding.has && (contentLengthStringLen || !transferEncoding.chunked));

if (transferEncoding.invalid && !deferredTransferEncodingError) [[unlikely]] {
Expand Down Expand Up @@ -1337,10 +1385,10 @@ struct HttpResponseData;

public:
template <bool IsNodeHttp>
HttpParserResult consumePostPadded(uint64_t maxHeaderSize, bool& isConnectRequest, bool requireHostHeader, bool useStrictMethodValidation, bool useInsecureHTTPParser, std::string *nodeHttpRequestTrailers, uint64_t *chunkedExtensionsByteCount, char *data, unsigned int length, void *user, void *reserved, MoveOnlyFunction<void *(void *, HttpRequest *)> &&requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &&dataHandler) {
HttpParserResult consumePostPadded(uint64_t maxHeaderSize, bool& isConnectRequest, bool requireHostHeader, bool useStrictMethodValidation, bool useInsecureHTTPParser, bool useLenientTransferEncoding, std::string *nodeHttpRequestTrailers, uint64_t *chunkedExtensionsByteCount, char *data, unsigned int length, void *user, void *reserved, MoveOnlyFunction<void *(void *, HttpRequest *)> &&requestHandler, MoveOnlyFunction<void *(void *, std::string_view, bool)> &&dataHandler) {
/* The fallback buffer may not exceed the configured per-request header
* limit (per-server maxHeaderSize can raise it above the default). */
const size_t maxFallbackSize = maxHeaderSize ? (size_t) maxHeaderSize : MAX_FALLBACK_SIZE;
const size_t maxFallbackSize = maxHeaderSize ? (size_t) (maxHeaderSize + MAX_HEADER_FRAMING_SLACK) : MAX_FALLBACK_SIZE;
/* This resets BloomFilter by construction, but later we also reset it again.
* Optimize this to skip resetting twice (req could be made global) */
HttpRequest req;
Expand Down Expand Up @@ -1411,7 +1459,7 @@ struct HttpResponseData;
fallback.append(data, maxCopyDistance);

// break here on break
HttpParserResult consumed = fenceAndConsumePostPadded<true, IsNodeHttp>(maxHeaderSize, isConnectRequest, requireHostHeader, useStrictMethodValidation, useInsecureHTTPParser, nodeHttpRequestTrailers, chunkedExtensionsByteCount, fallback.data(), (unsigned int) fallback.length(), user, reserved, &req, requestHandler, dataHandler);
HttpParserResult consumed = fenceAndConsumePostPadded<true, IsNodeHttp>(maxHeaderSize, isConnectRequest, requireHostHeader, useStrictMethodValidation, useInsecureHTTPParser, useLenientTransferEncoding, nodeHttpRequestTrailers, chunkedExtensionsByteCount, fallback.data(), (unsigned int) fallback.length(), user, reserved, &req, requestHandler, dataHandler);
/* Return data will be different than user if we are upgraded to WebSocket or have an error */
if (consumed.returnedData != user) {
return consumed;
Expand Down Expand Up @@ -1491,7 +1539,7 @@ struct HttpResponseData;
}
}

HttpParserResult consumed = fenceAndConsumePostPadded<false, IsNodeHttp>(maxHeaderSize, isConnectRequest, requireHostHeader, useStrictMethodValidation, useInsecureHTTPParser, nodeHttpRequestTrailers, chunkedExtensionsByteCount, data, length, user, reserved, &req, requestHandler, dataHandler);
HttpParserResult consumed = fenceAndConsumePostPadded<false, IsNodeHttp>(maxHeaderSize, isConnectRequest, requireHostHeader, useStrictMethodValidation, useInsecureHTTPParser, useLenientTransferEncoding, nodeHttpRequestTrailers, chunkedExtensionsByteCount, data, length, user, reserved, &req, requestHandler, dataHandler);
/* Return data will be different than user if we are upgraded to WebSocket or have an error */
if (consumed.returnedData != user) {
return consumed;
Expand Down
17 changes: 17 additions & 0 deletions src/http/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,23 @@ pub fn set_max_http_header_size(v: usize) {
MAX_HTTP_HEADER_SIZE.store(v, Ordering::Relaxed);
}

/// `--insecure-http-parser`: the process-wide default for node:http's
/// `insecureHTTPParser` option. Set once during single-threaded CLI parsing;
/// read from JS when node:http builds its parser leniency flags.
static INSECURE_HTTP_PARSER: AtomicBool = AtomicBool::new(false);

/// Safe accessor for `INSECURE_HTTP_PARSER`.
#[inline]
pub fn insecure_http_parser() -> bool {
INSECURE_HTTP_PARSER.load(Ordering::Relaxed)
}

/// Safe setter for `INSECURE_HTTP_PARSER` (see [`insecure_http_parser`]).
#[inline]
pub fn set_insecure_http_parser(v: bool) {
INSECURE_HTTP_PARSER.store(v, Ordering::Relaxed);
}

/// Set once during single-threaded CLI parsing; read from the HTTP thread.
pub static OVERRIDDEN_DEFAULT_USER_AGENT: std::sync::OnceLock<&'static [u8]> =
std::sync::OnceLock::new();
Expand Down
2 changes: 1 addition & 1 deletion src/js/internal/cluster/child.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@

if (accepted && server[owner_symbol]) {
const self = server[owner_symbol];
if (self.maxConnections != null && self._connections >= self.maxConnections) {
if (self.maxConnections != null && self._connections >= self.maxConnections && !self.dropMaxConnection) {

Check warning on line 219 in src/js/internal/cluster/child.ts

View check run for this annotation

Claude / Claude Code Review

dropMaxConnection guard added to a dead block (owner_symbol is a module-local Symbol)

The added `&& !self.dropMaxConnection` sits inside `if (accepted && server[owner_symbol])`, but `owner_symbol` at child.ts:18 is a fresh module-local `Symbol("owner_symbol")` — net.ts:120 defines its own separate one and writes to that key, so `server[owner_symbol]` here is always `undefined` and this block (and line 267's) never executes. The newly-enabled `test-http-server-drop-connections-in-cluster.js` passes via the native `onServerConnection` maxConnections gate this PR adds (http.Server u
Comment thread
robobun marked this conversation as resolved.
accepted = false;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/js/internal/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const {
server: any,
requireHostHeader: boolean,
useStrictMethodValidation: boolean,
insecureHTTPParser: boolean,
lenientHttpFlags: number,
maxHeaderSize: number,
onClientError: (ssl: boolean, socket: any, errorCode: number, rawPacket: ArrayBuffer) => undefined,
onConnection?: (socketHandle: any) => undefined,
Expand All @@ -34,7 +34,7 @@ const {
server: any,
requireHostHeader: boolean,
useStrictMethodValidation: boolean,
insecureHTTPParser: boolean,
lenientHttpFlags: number,
httpAllowHalfOpen: boolean,
) => void;
getCompleteWebRequestOrResponseBodyValueAsArrayBuffer: (arg: any) => ArrayBuffer | undefined;
Expand Down
Loading
Loading