diff --git a/lib/api/api-request.js b/lib/api/api-request.js index 285c76de241..868bb14b933 100644 --- a/lib/api/api-request.js +++ b/lib/api/api-request.js @@ -91,7 +91,8 @@ class RequestHandler extends AsyncResource { const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers const contentType = parsedHeaders['content-type'] - const body = new Readable({ resume, abort, contentType, highWaterMark }) + const contentLength = parsedHeaders['content-length'] + const body = new Readable({ resume, abort, contentType, contentLength, highWaterMark }) this.callback = null this.res = body diff --git a/lib/api/readable.js b/lib/api/readable.js index 25b40c109c0..8ae45011d46 100644 --- a/lib/api/readable.js +++ b/lib/api/readable.js @@ -11,8 +11,9 @@ const { ReadableStreamFrom } = require('../core/util') const kConsume = Symbol('kConsume') const kReading = Symbol('kReading') const kBody = Symbol('kBody') -const kAbort = Symbol('abort') +const kAbort = Symbol('kAbort') const kContentType = Symbol('kContentType') +const kContentLength = Symbol('kContentLength') const noop = () => {} @@ -21,6 +22,7 @@ module.exports = class BodyReadable extends Readable { resume, abort, contentType = '', + contentLength, highWaterMark = 64 * 1024 // Same as nodejs fs streams. }) { super({ @@ -35,6 +37,7 @@ module.exports = class BodyReadable extends Readable { this[kConsume] = null this[kBody] = null this[kContentType] = contentType + this[kContentLength] = contentLength // Is stream being consumed through Readable API? // This is an optimization so that we avoid checking @@ -146,7 +149,7 @@ module.exports = class BodyReadable extends Readable { } async dump (opts) { - let limit = Number.isFinite(opts?.limit) ? opts.limit : 262144 + let limit = Number.isFinite(opts?.limit) ? opts.limit : 128 * 1024 const signal = opts?.signal if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) { @@ -160,6 +163,10 @@ module.exports = class BodyReadable extends Readable { } return await new Promise((resolve, reject) => { + if (this[kContentLength] > limit) { + this.destroy(new AbortError()) + } + const onAbort = () => { this.destroy(signal.reason ?? new AbortError()) }