diff --git a/source/core/index.ts b/source/core/index.ts index 9553c915e..39a944a7a 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -1113,11 +1113,21 @@ export default class Request extends Duplex implements RequestEvents { const fn = options.cache ? this._createCacheableRequest : request; try { - let requestOrResponse = await fn(url, this._requestOptions); + // We can't do `await fn(...)`, + // because stream `error` event can be emitted before `Promise.resolve()`. + let requestOrResponse = fn(url, this._requestOptions); + + if (is.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + } // Fallback if (is.undefined(requestOrResponse)) { - requestOrResponse = await options.getFallbackRequestFunction()(url, this._requestOptions); + requestOrResponse = options.getFallbackRequestFunction()(url, this._requestOptions); + + if (is.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + } } if (isClientRequest(requestOrResponse!)) { diff --git a/test/http.ts b/test/http.ts index ff8e2e06e..eab945a97 100644 --- a/test/http.ts +++ b/test/http.ts @@ -357,3 +357,15 @@ test('JSON request custom stringifier', withServer, async (t, server, got) => { json: payload, })).body, customStringify(payload)); }); + +test('ClientRequest can throw before promise resolves', async t => { + await t.throwsAsync(got('http://example.com', { + dnsLookup: ((_hostname: string, _options: unknown, callback: Function) => { + queueMicrotask(() => { + callback(null, 'fe80::0000:0000:0000:0000', 6); + }); + }) as any + }), { + code: 'EINVAL' + }); +});