Skip to content

Commit 58dcdd0

Browse files
committed
fixup! http: add optimizeEmptyRequests server option
1 parent 78a0e8f commit 58dcdd0

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
@@ -3665,7 +3665,8 @@ changes:
36653665
* `optimizeEmptyRequests` {boolean} If set to `true`, requests without `Content-Length`
36663666
or `Transfer-Encoding` headers (indicating no body) will be initialized with an
36673667
already-ended body stream, so they will never emit any stream events
3668-
(like `data` or `end`). You can use `req.readableEnded` to detect this case.
3668+
(like `'data'` or `'end'`). You can use `req.readableEnded` to detect this case.
3669+
This option is still under experimental phase.
36693670
**Default:** `false`.
36703671
36713672
* `requestListener` {Function}

lib/_http_server.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,10 @@ function emitCloseNT(self) {
10741074
}
10751075
}
10761076

1077+
function hasBodyHeaders(headers) {
1078+
return ('content-length' in headers) || ('transfer-encoding' in headers);
1079+
}
1080+
10771081
// The following callback is issued after the headers have been read on a
10781082
// new message. In this callback we setup the response object and pass it
10791083
// to the user.
@@ -1126,11 +1130,11 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
11261130
}
11271131

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

11321135
if (shouldOptimize) {
1133-
// Fast processing where request "has" already emitted all lifecycle events.
1136+
// Fast processing where emitting 'data', 'end' and 'close' events is
1137+
// skipped and data is dumped.
11341138
// This avoids a lot of unnecessary overhead otherwise introduced by
11351139
// stream.Readable life cycle rules. The downside is that this will
11361140
// 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)