From 226cc3995f6e16938163ebde24d8762e7dcd15e2 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Mon, 12 Jul 2021 16:35:12 +0200 Subject: [PATCH] Fix `Cannot call end` error when `request` returns a `Writable` --- source/core/index.ts | 6 ++++++ test/stream.ts | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/source/core/index.ts b/source/core/index.ts index b5b0525bf..81228384d 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -467,6 +467,12 @@ export default class Request extends Duplex implements RequestEvents { } this._request.end((error?: Error | null) => { + // The request has been destroyed before `_final` finished. + // See https://github.com/nodejs/node/issues/39356 + if ((this._request as any)._writableState?.errored) { + return; + } + if (!error) { this._bodySize = this._uploadedSize; diff --git a/test/stream.ts b/test/stream.ts index 921eac50f..d20c8ce66 100644 --- a/test/stream.ts +++ b/test/stream.ts @@ -1,7 +1,7 @@ import {promisify} from 'util'; import fs from 'fs'; import {Agent as HttpAgent} from 'http'; -import stream, {PassThrough as PassThroughStream, Readable as ReadableStream} from 'stream'; +import stream, {PassThrough as PassThroughStream, Readable as ReadableStream, Writable} from 'stream'; import {Readable as Readable2} from 'readable-stream'; import test from 'ava'; import {Handler} from 'express'; @@ -497,6 +497,20 @@ test('accepts readable-stream as body', withServer, async (t, server, got) => { t.is(response.body, 'ok'); }); +test('prevents `Cannot call end` error', async t => { + const stream = got.stream('https://example.com', { + request: () => new Writable({ + final() {} + }) as any, + timeout: { + request: 1 + } + }); + + const error: RequestError = await pEvent(stream, 'error'); + t.is(error.code, 'ETIMEDOUT'); +}); + if (Number.parseInt(process.versions.node.split('.')[0]!, 10) <= 12) { test('does not emit end event on error', withServer, async (t, server, got) => { server.get('/', infiniteHandler);