Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
6735585
deps: update googletest to 279f847
nodejs-github-bot Oct 14, 2025
42729f0
src: stop using deprecated v8::Context::GetIsolate
targos Oct 14, 2025
8c8525c
doc: fix not working code example in vm docs
arturgawlik Oct 14, 2025
64fc625
inspector: support handshake response for websocket inspection
islandryu Oct 14, 2025
4395fe1
http: add optimizeEmptyRequests server option
RafaelGSS Oct 14, 2025
be1b84f
module: handle null source from async loader hooks in sync hooks
joyeecheung Oct 14, 2025
f1aa1ea
inspector: add network payload buffer size limits
legendecas Oct 15, 2025
21bcd0e
deps: V8: cherry-pick 3d0f462a17ff
joyeecheung Sep 16, 2025
1bbcdf9
benchmark: add vm.SourceTextModule benchmark
joyeecheung Oct 10, 2025
6f3b16d
esm: use index-based resolution callbacks
joyeecheung Aug 7, 2025
a40e533
src: add a default branch for module phase
legendecas Oct 15, 2025
14f3189
tools: add inspector_protocol updater
legendecas Oct 15, 2025
0f0d3c0
doc: fix `blob.bytes()` heading level
xty Oct 16, 2025
8492bc6
doc: add --heap-snapshot-on-oom to useful v8 flag
jakecastelli Oct 17, 2025
afdb362
src: use `Utf8Value` and `TwoByteValue` instead of V8 helpers
addaleax Oct 13, 2025
11ebb04
tools: add C++ lint rule to avoid using `String::Utf8Value`
addaleax Oct 13, 2025
5dd670b
src: initial enablement of IsolateGroups
jasnell Oct 17, 2025
8caae1a
test: move sea tests into test/sea
joyeecheung Oct 13, 2025
26b01bf
test: skip sea tests on x64 macOS
joyeecheung Oct 13, 2025
bac70c6
doc: document wildcard supported by tools/test.py
joyeecheung Oct 17, 2025
ffeebeb
test: make test-worker-prof more tolerant
joyeecheung Oct 17, 2025
405a9c4
test: parallelize test-without-async-context-frame correctly
joyeecheung Oct 17, 2025
9ecaf41
typings: delete undefined property in ConfigBinding
whsung0330 Oct 14, 2025
09ae6fc
typings: add missing properties in HTTPParser
whsung0330 Oct 14, 2025
ef4c596
typings: add missing properties and method in Worker
whsung0330 Oct 14, 2025
e3c3b48
test: ignore EPIPE errors in https proxy invalid URL test
joyeecheung Oct 18, 2025
df8396a
src: replace Environment::GetCurrent with args.GetIsolate
KimSH39 Oct 18, 2025
47fa765
tools: optimize wildcard execution in tools/test.py
joyeecheung Oct 18, 2025
e600711
benchmark: add benchmark for leaf source text modules
joyeecheung Oct 12, 2025
79b2387
vm: make vm.Module.evaluate() conditionally synchronous
joyeecheung Oct 10, 2025
30451d3
test: fix incorrect calculation in test-perf-hooks.js
joyeecheung Oct 18, 2025
8a6de38
doc, assert: correct order of changes entries
Flarna Oct 18, 2025
9e6d6ce
util: mark special properties when inspecting them
BridgeAR Oct 18, 2025
a507308
tools: fix inspector_protocol updater
legendecas Oct 18, 2025
8ccff0d
doc: update decorator documentation to reflect actual policy
salman-aziz-4425 Oct 19, 2025
36837fa
src: use cached primordials_string
KimSH39 Oct 19, 2025
04cc7aa
build: remove V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE defs
joyeecheung Oct 19, 2025
a07f32e
test: split test-runner-watch-mode-kill-signal
joyeecheung Oct 19, 2025
59223a7
meta: loop userland-migrations in deprecations
legendecas Oct 19, 2025
17fde3f
build: build v8 with -fvisibility=hidden -fvisibility-inlines-hidden
joyeecheung Oct 19, 2025
4b23ac8
test: fix status when compiled without inspector
aduh95 Oct 19, 2025
99e357a
doc: use `any` for `worker_threads.Worker` 'error' event argument `err`
jonasgeiler Oct 19, 2025
f437204
src: add watch config namespace
marco-ippolito Oct 9, 2025
4a86016
util: use more defensive code when inspecting error objects
aduh95 Oct 20, 2025
a02897e
meta: move one or more collaborators to emeritus
nodejs-github-bot Oct 20, 2025
8596891
deps: update inspector_protocol to af7f5a8173fdbc29f0835ec94395932e328b
nodejs-github-bot Oct 21, 2025
aacfc0d
deps: update corepack to 0.34.1
nodejs-github-bot Oct 21, 2025
9310284
build: use call command when calling python configure
ZenMasterJacob20011 Oct 21, 2025
6e8b029
tools: limit inspector protocol PR title length
legendecas Oct 21, 2025
063fbd8
msi: fix WiX warnings
StefanStojanovic Oct 22, 2025
3d89331
test_runner: use module.registerHooks in module mocks
joyeecheung Oct 22, 2025
6bacb65
doc, module: change async customization hooks to experimental
Flarna Oct 22, 2025
6de2407
test: fix small compile warning in test_network_requests_buffer.cc
xiaocainiao633 Oct 22, 2025
e8fdd8d
tools: update gyp-next to 0.20.5
nodejs-github-bot Oct 22, 2025
064c8c5
doc: add missing CAA type to dns.resolveAny() & dnsPromises.resolveAny()
hkleungai Oct 22, 2025
2d48d17
module: refactor and clarify async loader hook customizations
joyeecheung Oct 23, 2025
22fa6bd
build: ibmi follow aix visibility
sravani1510 Oct 24, 2025
563e131
doc: remove unnecessary statement of web storage
deokjinkim Oct 24, 2025
0b38de3
test: put helper in test-runner-output into common
joyeecheung Oct 24, 2025
12773d1
test: increase debugger waitFor timeout on macOS
legendecas Oct 24, 2025
e83dbcb
test,crypto: sha3 algorithms aren't supported with BoringSSL
codebytere Oct 25, 2025
8a20530
crypto: update root certificates to NSS 3.116
nodejs-github-bot Oct 25, 2025
e5559f3
win: upgrade Visual Studio workload from 2019 to 2022
gengjiawen Oct 25, 2025
3d183e3
test,crypto: fix conditional SHA3-* skip on BoringSSL
panva Oct 25, 2025
29a5855
test: ensure assertions are reachable in `test/addons`
aduh95 Oct 25, 2025
4a5d7a4
src: conditionally disable source phase imports by default
codebytere Oct 26, 2025
377e8ce
tls: avoid external memory leak on invalid protocol versions
codebytere Oct 26, 2025
7a6542c
test: skip failing test on macOS 15.7+
aduh95 Oct 26, 2025
5d5c848
tools: run CI with shared libs on GHA
aduh95 Oct 17, 2025
f402b4e
tools: show diff alongside the error in Nix linter
aduh95 Oct 19, 2025
ffec592
meta: fix typo in test-shared workflow name
Ronitsabhaya75 Oct 19, 2025
03b0347
tools: disable inspector on macOS-shared to reduce flakiness
aduh95 Oct 21, 2025
cb615b1
tools: skip test-shared workflow for draft PRs
targos Oct 24, 2025
ae4858c
tools: add an option to generate lighter archives
aduh95 Sep 8, 2025
425a187
doc: mention more codemods in `deprecations.md`
AugustinMauroy Oct 27, 2025
95644a4
http: lazy allocate cookies array
ronag Oct 27, 2025
2e55c6a
sqlite: allow setting defensive flag
louwers Oct 27, 2025
bb27766
benchmark: improve cpu.sh for safety and usability
meteorqz6 Oct 27, 2025
fe91c0f
deps: update simdjson to 4.0.7
nodejs-github-bot Oct 27, 2025
0ecbb80
lib: fix typo in createBlobReaderStream
SeokhunEom Oct 27, 2025
267e1b3
src: add COUNT_GENERIC_USAGE utility for tests
joyeecheung Oct 27, 2025
dc93d69
src: fix timing of snapshot serialize callback
joyeecheung Oct 27, 2025
1da054d
2025-10-28, Version 25.1.0 (Current)
aduh95 Oct 28, 2025
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
Prev Previous commit
Next Next commit
http: add optimizeEmptyRequests server option
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
Co-Authored-By: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: #59778
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
  • Loading branch information
RafaelGSS authored and aduh95 committed Oct 23, 2025
commit 4395fe14b9002171defd4fb896adbd2bf4d93d13
8 changes: 8 additions & 0 deletions doc/api/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -3555,6 +3555,9 @@ Found'`.
<!-- YAML
added: v0.1.13
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/59778
description: Add optimizeEmptyRequests option.
- version: v24.9.0
pr-url: https://github.com/nodejs/node/pull/59824
description: The `shouldUpgradeCallback` option is now supported.
Expand Down Expand Up @@ -3660,6 +3663,11 @@ changes:
* `rejectNonStandardBodyWrites` {boolean} If set to `true`, an error is thrown
when writing to an HTTP response which does not have a body.
**Default:** `false`.
* `optimizeEmptyRequests` {boolean} If set to `true`, requests without `Content-Length`
or `Transfer-Encoding` headers (indicating no body) will be initialized with an
already-ended body stream, so they will never emit any stream events
(like `'data'` or `'end'`). You can use `req.readableEnded` to detect this case.
**Default:** `false`.

* `requestListener` {Function}

Expand Down
9 changes: 9 additions & 0 deletions lib/_http_incoming.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,15 @@ function _addHeaderLineDistinct(field, value, dest) {
}
}

IncomingMessage.prototype._dumpAndCloseReadable = function _dumpAndCloseReadable() {
this._dumped = true;
this._readableState.ended = true;
this._readableState.endEmitted = true;
this._readableState.destroyed = true;
this._readableState.closed = true;
this._readableState.closeEmitted = true;
};


// Call this instead of resume() if we want to just
// dump all the data to /dev/null
Expand Down
24 changes: 24 additions & 0 deletions lib/_http_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ const onResponseFinishChannel = dc.channel('http.server.response.finish');
const kServerResponse = Symbol('ServerResponse');
const kServerResponseStatistics = Symbol('ServerResponseStatistics');

const kOptimizeEmptyRequests = Symbol('OptimizeEmptyRequestsOption');

const {
hasObserver,
startPerf,
Expand Down Expand Up @@ -455,6 +457,11 @@ function storeHTTPOptions(options) {
validateInteger(maxHeaderSize, 'maxHeaderSize', 0);
this.maxHeaderSize = maxHeaderSize;

const optimizeEmptyRequests = options.optimizeEmptyRequests;
if (optimizeEmptyRequests !== undefined)
validateBoolean(optimizeEmptyRequests, 'options.optimizeEmptyRequests');
this[kOptimizeEmptyRequests] = optimizeEmptyRequests || false;

const insecureHTTPParser = options.insecureHTTPParser;
if (insecureHTTPParser !== undefined)
validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
Expand Down Expand Up @@ -1069,6 +1076,10 @@ function emitCloseNT(self) {
}
}

function hasBodyHeaders(headers) {
return ('content-length' in headers) || ('transfer-encoding' in headers);
}

// The following callback is issued after the headers have been read on a
// new message. In this callback we setup the response object and pass it
// to the user.
Expand Down Expand Up @@ -1120,6 +1131,19 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
});
}

// Check if we should optimize empty requests (those without Content-Length or Transfer-Encoding headers)
const shouldOptimize = server[kOptimizeEmptyRequests] === true && !hasBodyHeaders(req.headers);

if (shouldOptimize) {
// Fast processing where emitting 'data', 'end' and 'close' events is
// skipped and data is dumped.
// This avoids a lot of unnecessary overhead otherwise introduced by
// stream.Readable life cycle rules. The downside is that this will
// break some servers that read bodies for methods that don't have body headers.
req._dumpAndCloseReadable();
req._read();
}

if (socket._httpMessage) {
// There are already pending outgoing res, append.
state.outgoing.push(res);
Expand Down
77 changes: 77 additions & 0 deletions test/parallel/test-http-server-optimize-empty-requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const http = require('http');
const net = require('net');

let reqs = 0;
let optimizedReqs = 0;
const server = http.createServer({
optimizeEmptyRequests: true
}, (req, res) => {
reqs++;
if (req._dumped) {
optimizedReqs++;
req.on('data', common.mustNotCall());
req.on('end', common.mustNotCall());

assert.strictEqual(req._dumped, true);
assert.strictEqual(req.readableEnded, true);
assert.strictEqual(req.destroyed, true);
}
res.writeHead(200);
res.end('ok');
});

server.listen(0, common.mustCall(async () => {
// GET request without Content-Length (should be optimized)
const getRequest = 'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n';
await makeRequest(getRequest);

// HEAD request (should always be optimized regardless of headers)
const headRequest = 'HEAD / HTTP/1.1\r\nHost: localhost\r\n\r\n';
await makeRequest(headRequest);

// POST request without body headers (should be optimized)
const postWithoutBodyHeaders = 'POST / HTTP/1.1\r\nHost: localhost\r\n\r\n';
await makeRequest(postWithoutBodyHeaders);

// DELETE request without body headers (should be optimized)
const deleteWithoutBodyHeaders = 'DELETE / HTTP/1.1\r\nHost: localhost\r\n\r\n';
await makeRequest(deleteWithoutBodyHeaders);

// POST request with Content-Length header (should not be optimized)
const postWithContentLength = 'POST / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n\r\n';
await makeRequest(postWithContentLength);

// GET request with Content-Length header (should not be optimized)
const getWithContentLength = 'GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n\r\n';
await makeRequest(getWithContentLength);

// POST request with Transfer-Encoding header (should not be optimized)
const postWithTransferEncoding = 'POST / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n';
await makeRequest(postWithTransferEncoding);

// GET request with Transfer-Encoding header (should not be optimized)
const getWithTransferEncoding = 'GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n';
await makeRequest(getWithTransferEncoding);

server.close();

assert.strictEqual(reqs, 8, `Expected 8 requests but got ${reqs}`);
assert.strictEqual(optimizedReqs, 4, `Expected 4 optimized requests but got ${optimizedReqs}`);
}));

function makeRequest(str) {
return new Promise((resolve) => {
const client = net.connect({ port: server.address().port }, common.mustCall(() => {
client.on('data', () => {});
client.on('end', common.mustCall(() => {
resolve();
}));
client.write(str);
client.end();
}));
});
}