summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGerrard Lindsay <gerrardalindsay@gmail.com>2023-05-13 13:09:26 -0400
committerGitHub <noreply@github.com>2023-05-13 17:09:26 +0000
commit5ec0f39a7a565b5a82fe90ba9f095731a7b8b005 (patch)
tree20c8778d8d43f2862b59f97b3d84002753fd4759 /lib
parent23e6b12edb0b792b82ff948e3b6c5cb2038c17bf (diff)
downloadnode-new-5ec0f39a7a565b5a82fe90ba9f095731a7b8b005.tar.gz
http: prevent writing to the body when not allowed by HTTP spec
PR-URL: https://github.com/nodejs/node/pull/47732 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/_http_outgoing.js21
-rw-r--r--lib/_http_server.js14
-rw-r--r--lib/http.js1
-rw-r--r--lib/internal/errors.js2
4 files changed, 30 insertions, 8 deletions
diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js
index 55a2f8bef3..73bd2aad8f 100644
--- a/lib/_http_outgoing.js
+++ b/lib/_http_outgoing.js
@@ -60,6 +60,7 @@ const {
ERR_HTTP_HEADERS_SENT,
ERR_HTTP_INVALID_HEADER_VALUE,
ERR_HTTP_TRAILER_INVALID,
+ ERR_HTTP_BODY_NOT_ALLOWED,
ERR_INVALID_HTTP_TOKEN,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
@@ -85,6 +86,7 @@ const kUniqueHeaders = Symbol('kUniqueHeaders');
const kBytesWritten = Symbol('kBytesWritten');
const kErrored = Symbol('errored');
const kHighWaterMark = Symbol('kHighWaterMark');
+const kRejectNonStandardBodyWrites = Symbol('kRejectNonStandardBodyWrites');
const nop = () => {};
@@ -150,6 +152,7 @@ function OutgoingMessage(options) {
this[kErrored] = null;
this[kHighWaterMark] = options?.highWaterMark ?? getDefaultHighWaterMark();
+ this[kRejectNonStandardBodyWrites] = options?.rejectNonStandardBodyWrites ?? false;
}
ObjectSetPrototypeOf(OutgoingMessage.prototype, Stream.prototype);
ObjectSetPrototypeOf(OutgoingMessage, Stream);
@@ -884,6 +887,17 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
err = new ERR_STREAM_DESTROYED('write');
}
+ if (!msg._hasBody) {
+ if (msg[kRejectNonStandardBodyWrites]) {
+ throw new ERR_HTTP_BODY_NOT_ALLOWED();
+ } else {
+ debug('This type of response MUST NOT have a body. ' +
+ 'Ignoring write() calls.');
+ process.nextTick(callback);
+ return true;
+ }
+ }
+
if (err) {
if (!msg.destroyed) {
onError(msg, err, callback);
@@ -916,13 +930,6 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
msg._implicitHeader();
}
- if (!msg._hasBody) {
- debug('This type of response MUST NOT have a body. ' +
- 'Ignoring write() calls.');
- process.nextTick(callback);
- return true;
- }
-
if (!fromEnd && msg.socket && !msg.socket.writableCorked) {
msg.socket.cork();
process.nextTick(connectionCorkNT, msg.socket);
diff --git a/lib/_http_server.js b/lib/_http_server.js
index 774bdc368f..c6a0701155 100644
--- a/lib/_http_server.js
+++ b/lib/_http_server.js
@@ -487,6 +487,14 @@ function storeHTTPOptions(options) {
validateBoolean(joinDuplicateHeaders, 'options.joinDuplicateHeaders');
}
this.joinDuplicateHeaders = joinDuplicateHeaders;
+
+ const rejectNonStandardBodyWrites = options.rejectNonStandardBodyWrites;
+ if (rejectNonStandardBodyWrites !== undefined) {
+ validateBoolean(rejectNonStandardBodyWrites, 'options.rejectNonStandardBodyWrites');
+ this.rejectNonStandardBodyWrites = rejectNonStandardBodyWrites;
+ } else {
+ this.rejectNonStandardBodyWrites = false;
+ }
}
function setupConnectionsTracking(server) {
@@ -1023,7 +1031,11 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
}
}
- const res = new server[kServerResponse](req, { highWaterMark: socket.writableHighWaterMark });
+ const res = new server[kServerResponse](req,
+ {
+ highWaterMark: socket.writableHighWaterMark,
+ rejectNonStandardBodyWrites: server.rejectNonStandardBodyWrites,
+ });
res._keepAliveTimeout = server.keepAliveTimeout;
res._maxRequestsPerSocket = server.maxRequestsPerSocket;
res._onPendingData = updateOutgoingData.bind(undefined,
diff --git a/lib/http.js b/lib/http.js
index a1f811c695..d86d36d12c 100644
--- a/lib/http.js
+++ b/lib/http.js
@@ -55,6 +55,7 @@ let maxHeaderSize;
* requireHostHeader?: boolean;
* joinDuplicateHeaders?: boolean;
* highWaterMark?: number;
+ * rejectNonStandardBodyWrites?: boolean;
* }} [opts]
* @param {Function} [requestListener]
* @returns {Server}
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 18f4a2c42c..8a490ea3a4 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1154,6 +1154,8 @@ E('ERR_HTTP2_TRAILERS_NOT_READY',
'Trailing headers cannot be sent until after the wantTrailers event is ' +
'emitted', Error);
E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.', Error);
+E('ERR_HTTP_BODY_NOT_ALLOWED',
+ 'Adding content for this request method or response status is not allowed.', Error);
E('ERR_HTTP_CONTENT_LENGTH_MISMATCH',
'Response body\'s content-length of %s byte(s) does not match the content-length of %s byte(s) set in header', Error);
E('ERR_HTTP_HEADERS_SENT',