Skip to content

Commit 50a0195

Browse files
committed
fixup! http: add optimizeEmptyRequests server option
1 parent b716d09 commit 50a0195

File tree

5 files changed

+41
-22
lines changed

5 files changed

+41
-22
lines changed

doc/api/http.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3638,7 +3638,8 @@ changes:
36383638
* `optimizeEmptyRequests` {boolean} If set to `true`, requests without `Content-Length`
36393639
or `Transfer-Encoding` headers (indicating no body) will be initialized with an
36403640
already-ended body stream, so they will never emit any stream events
3641-
(like `data` or `end`). You can use `req.readableEnded` to detect this case.
3641+
(like `'data'` or `'end'`). You can use `req.readableEnded` to detect this case.
3642+
This option is still under experimental phase.
36423643
**Default:** `false`.
36433644
36443645
* `requestListener` {Function}

lib/_http_server.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,10 @@ function emitCloseNT(self) {
10581058
}
10591059
}
10601060

1061+
function hasBodyHeaders(headers) {
1062+
return ('content-length' in headers) || ('transfer-encoding' in headers);
1063+
}
1064+
10611065
// The following callback is issued after the headers have been read on a
10621066
// new message. In this callback we setup the response object and pass it
10631067
// to the user.
@@ -1110,11 +1114,11 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
11101114
}
11111115

11121116
// Check if we should optimize empty requests (those without Content-Length or Transfer-Encoding headers)
1113-
const hasBodyHeaders = ('content-length' in req.headers) || ('transfer-encoding' in req.headers);
1114-
const shouldOptimize = server[kOptimizeEmptyRequests] === true && !hasBodyHeaders;
1117+
const shouldOptimize = server[kOptimizeEmptyRequests] === true && !hasBodyHeaders(req.headers);
11151118

11161119
if (shouldOptimize) {
1117-
// Fast processing where request "has" already emitted all lifecycle events.
1120+
// Fast processing where emitting 'data', 'end' and 'close' events is
1121+
// skipped and data is dumped.
11181122
// This avoids a lot of unnecessary overhead otherwise introduced by
11191123
// stream.Readable life cycle rules. The downside is that this will
11201124
// break some servers that read bodies for methods that don't have body headers.

test/parallel/test-http-chunk-extensions-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ const assert = require('assert');
124124
}));
125125

126126
sock.end('' +
127-
'PUT / HTTP/1.1\r\n' +
127+
'GET / HTTP/1.1\r\n' +
128128
`Host: localhost:${port}\r\n` +
129129
'Transfer-Encoding: chunked\r\n\r\n' +
130130
'2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' +

test/parallel/test-http-server-optimize-empty-requests.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@ const http = require('http');
66
const net = require('net');
77

88
let reqs = 0;
9+
let optimizedReqs = 0;
910
const server = http.createServer({
1011
optimizeEmptyRequests: true
1112
}, (req, res) => {
1213
reqs++;
13-
req.on('data', common.mustNotCall());
14-
req.on('end', common.mustNotCall());
15-
16-
assert.strictEqual(req._dumped, true);
17-
assert.strictEqual(req._readableState.ended, true);
18-
assert.strictEqual(req._readableState.endEmitted, true);
19-
assert.strictEqual(req._readableState.destroyed, true);
14+
if (req._dumped) {
15+
optimizedReqs++;
16+
req.on('data', common.mustNotCall());
17+
req.on('end', common.mustNotCall());
2018

19+
assert.strictEqual(req._dumped, true);
20+
assert.strictEqual(req.readableEnded, true);
21+
assert.strictEqual(req.destroyed, true);
22+
}
2123
res.writeHead(200);
2224
res.end('ok');
2325
});
@@ -38,9 +40,27 @@ server.listen(0, common.mustCall(async () => {
3840
// DELETE request without body headers (should be optimized)
3941
const deleteWithoutBodyHeaders = 'DELETE / HTTP/1.1\r\nHost: localhost\r\n\r\n';
4042
await makeRequest(deleteWithoutBodyHeaders);
43+
44+
// POST request with Content-Length header (should not be optimized)
45+
const postWithContentLength = 'POST / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n\r\n';
46+
await makeRequest(postWithContentLength);
47+
48+
// GET request with Content-Length header (should not be optimized)
49+
const getWithContentLength = 'GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n\r\n';
50+
await makeRequest(getWithContentLength);
51+
52+
// POST request with Transfer-Encoding header (should not be optimized)
53+
const postWithTransferEncoding = 'POST / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n';
54+
await makeRequest(postWithTransferEncoding);
55+
56+
// GET request with Transfer-Encoding header (should not be optimized)
57+
const getWithTransferEncoding = 'GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n';
58+
await makeRequest(getWithTransferEncoding);
59+
4160
server.close();
4261

43-
assert.strictEqual(reqs, 4);
62+
assert.strictEqual(reqs, 8, `Expected 8 requests but got ${reqs}`);
63+
assert.strictEqual(optimizedReqs, 4, `Expected 4 optimized requests but got ${optimizedReqs}`);
4464
}));
4565

4666
function makeRequest(str) {

test/parallel/test-http.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,12 @@ const server = http.Server(common.mustCall((req, res) => {
5252
if (expectedRequests.length === 0)
5353
server.close();
5454

55-
if (req.readableEnded) {
55+
req.on('end', () => {
5656
res.writeHead(200, { 'Content-Type': 'text/plain' });
5757
res.write(`The path was ${url.parse(req.url).pathname}`);
5858
res.end();
59-
} else {
60-
req.on('end', () => {
61-
res.writeHead(200, { 'Content-Type': 'text/plain' });
62-
res.write(`The path was ${url.parse(req.url).pathname}`);
63-
res.end();
64-
});
65-
req.resume();
66-
}
59+
});
60+
req.resume();
6761
}, 3));
6862
server.listen(0);
6963

0 commit comments

Comments
 (0)