http: add optimizeEmptyRequests server option · nodejs/node@619f6bb · GitHub
Skip to content

Commit 619f6bb

Browse files
RafaelGSSaduh95
authored andcommitted
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>
1 parent 0007212 commit 619f6bb

4 files changed

Lines changed: 118 additions & 0 deletions

File tree

doc/api/http.md

Lines changed: 8 additions & 0 deletions

lib/_http_incoming.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,15 @@ function _addHeaderLineDistinct(field, value, dest) {
423423
}
424424
}
425425

426+
IncomingMessage.prototype._dumpAndCloseReadable = function _dumpAndCloseReadable() {
427+
this._dumped = true;
428+
this._readableState.ended = true;
429+
this._readableState.endEmitted = true;
430+
this._readableState.destroyed = true;
431+
this._readableState.closed = true;
432+
this._readableState.closeEmitted = true;
433+
};
434+
426435

427436
// Call this instead of resume() if we want to just
428437
// dump all the data to /dev/null

lib/_http_server.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ const onResponseFinishChannel = dc.channel('http.server.response.finish');
106106
const kServerResponse = Symbol('ServerResponse');
107107
const kServerResponseStatistics = Symbol('ServerResponseStatistics');
108108

109+
const kOptimizeEmptyRequests = Symbol('OptimizeEmptyRequestsOption');
110+
109111
const {
110112
hasObserver,
111113
startPerf,
@@ -453,6 +455,11 @@ function storeHTTPOptions(options) {
453455
validateInteger(maxHeaderSize, 'maxHeaderSize', 0);
454456
this.maxHeaderSize = maxHeaderSize;
455457

458+
const optimizeEmptyRequests = options.optimizeEmptyRequests;
459+
if (optimizeEmptyRequests !== undefined)
460+
validateBoolean(optimizeEmptyRequests, 'options.optimizeEmptyRequests');
461+
this[kOptimizeEmptyRequests] = optimizeEmptyRequests || false;
462+
456463
const insecureHTTPParser = options.insecureHTTPParser;
457464
if (insecureHTTPParser !== undefined)
458465
validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
@@ -1067,6 +1074,10 @@ function emitCloseNT(self) {
10671074
}
10681075
}
10691076

1077+
function hasBodyHeaders(headers) {
1078+
return ('content-length' in headers) || ('transfer-encoding' in headers);
1079+
}
1080+
10701081
// The following callback is issued after the headers have been read on a
10711082
// new message. In this callback we setup the response object and pass it
10721083
// to the user.
@@ -1118,6 +1129,19 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
11181129
});
11191130
}
11201131

1132+
// Check if we should optimize empty requests (those without Content-Length or Transfer-Encoding headers)
1133+
const shouldOptimize = server[kOptimizeEmptyRequests] === true && !hasBodyHeaders(req.headers);
1134+
1135+
if (shouldOptimize) {
1136+
// Fast processing where emitting 'data', 'end' and 'close' events is
1137+
// skipped and data is dumped.
1138+
// This avoids a lot of unnecessary overhead otherwise introduced by
1139+
// stream.Readable life cycle rules. The downside is that this will
1140+
// break some servers that read bodies for methods that don't have body headers.
1141+
req._dumpAndCloseReadable();
1142+
req._read();
1143+
}
1144+
11211145
if (socket._httpMessage) {
11221146
// There are already pending outgoing res, append.
11231147
state.outgoing.push(res);
Lines changed: 77 additions & 0 deletions

0 commit comments

Comments
 (0)