From aea34a9ad169625df7c8b626ed2e6126388d1f33 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 20 Oct 2025 11:09:22 +0200 Subject: [PATCH] fix(interceptor/dump): fix handler lifecycle violation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dump interceptor was calling super.onResponseEnd() from within onResponseData() when the size limit was reached. This violates the handler lifecycle and causes the response handling to complete prematurely while data is still being received. Changes: - onResponseData: Set #dumped flag when size >= maxSize but don't call super.onResponseEnd() prematurely - onResponseEnd: Call super.onResponseEnd() only when the HTTP response actually ends, checking the #dumped flag - Fixed abort handling to check this.#controller.aborted Note: Tests still timeout due to a separate issue in the body stream implementation (lib/api/api-request.js). When Content-Length is set but no data is passed to the body stream (because we're dumping it), the stream hangs waiting for data. This needs to be addressed in a follow-up fix. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Signed-off-by: Matteo Collina --- lib/interceptor/dump.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/interceptor/dump.js b/lib/interceptor/dump.js index 4810a09f382..f5a25c8b2ba 100644 --- a/lib/interceptor/dump.js +++ b/lib/interceptor/dump.js @@ -19,7 +19,6 @@ class DumpHandler extends DecoratorHandler { super(handler) this.#maxSize = maxSize ?? this.#maxSize - // this.#handler = handler } #abort (reason) { @@ -46,7 +45,7 @@ class DumpHandler extends DecoratorHandler { } if (this.aborted === true) { - return true + return super.onResponseStart(controller, statusCode, headers, statusMessage) } return super.onResponseStart(controller, statusCode, headers, statusMessage) @@ -68,24 +67,22 @@ class DumpHandler extends DecoratorHandler { if (this.#size >= this.#maxSize) { this.#dumped = true - - if (this.aborted === true) { - super.onResponseError(controller, this.reason) - } else { - super.onResponseEnd(controller, {}) - } } + // Don't pass data to handler - we're dumping/discarding it + // Return true to indicate we've consumed the data return true } onResponseEnd (controller, trailers) { - if (this.#dumped) { + if (this.#controller.aborted === true) { + super.onResponseError(controller, this.reason) return } - if (this.#controller.aborted === true) { - super.onResponseError(controller, this.reason) + if (this.#dumped) { + // Response was dumped, end with empty trailers + super.onResponseEnd(controller, {}) return }