From 30b782d947c01a3aa659d1079b2739ffb816f550 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Mon, 2 Nov 2020 14:23:52 +0100 Subject: [PATCH 1/6] Add read timeout --- source/core/utils/timed-out.ts | 25 ++++++++++++++++--------- test/timeout.ts | 29 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/source/core/utils/timed-out.ts b/source/core/utils/timed-out.ts index ae14ce1ac..80d1d6d1f 100644 --- a/source/core/utils/timed-out.ts +++ b/source/core/utils/timed-out.ts @@ -13,11 +13,13 @@ interface TimedOutOptions { export interface Delays { lookup?: number; + socket?: number; connect?: number; secureConnect?: number; - socket?: number; - response?: number; send?: number; + response?: number; + read?: number; + request?: number; } @@ -89,14 +91,12 @@ export default (request: ClientRequest, delays: Delays, options: TimedOutOptions } }); - request.once('close', cancelTimeouts); - - once(request, 'response', (response: IncomingMessage): void => { - once(response, 'end', cancelTimeouts); - }); - if (typeof delays.request !== 'undefined') { - addTimeout(delays.request, timeoutHandler, 'request'); + const cancelTimeout = addTimeout(delays.request, timeoutHandler, 'request'); + + once(request, 'response', (response: IncomingMessage): void => { + once(response, 'end', cancelTimeout); + }); } if (typeof delays.socket !== 'undefined') { @@ -168,6 +168,13 @@ export default (request: ClientRequest, delays: Delays, options: TimedOutOptions }); } + if (typeof delays.read !== 'undefined') { + once(request, 'response', (response: IncomingMessage): void => { + const cancelTimeout = addTimeout(delays.read!, timeoutHandler, 'read'); + once(response, 'end', cancelTimeout); + }); + } + return cancelTimeouts; }; diff --git a/test/timeout.ts b/test/timeout.ts index de5b347c2..4a3e33639 100644 --- a/test/timeout.ts +++ b/test/timeout.ts @@ -642,6 +642,35 @@ test.serial('no unhandled `Premature close` error', withServer, async (t, server await delay(20); }); +// TODO: use fakeTimers here +test.serial('`read` timeout - promise', withServer, async (t, server, got) => { + server.get('/', (_request, response) => { + response.write('o'); + }); + + await t.throwsAsync(got({ + timeout: { + read: 10 + }, + retry: 0 + }), {message: 'Timeout awaiting \'read\' for 10ms'}); +}); + +// TODO: use fakeTimers here +test.serial.only('`read` timeout - stream', withServer, async (t, server, got) => { + server.get('/', (_request, response) => { + response.end('ok'); + }); + + const stream = got.stream({ + timeout: { + read: 10 + } + }); + + await t.throwsAsync(pEvent(stream, 'end'), {message: 'Timeout awaiting \'read\' for 10ms'}); +}); + // TODO: use fakeTimers here test.serial('cancelling the request removes timeouts', withServer, async (t, server, got) => { server.get('/', (_request, response) => { From 07cc04e629ec8fac0ff9d2418a2a72f853901590 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Fri, 26 Feb 2021 13:59:32 +0100 Subject: [PATCH 2/6] Add docs --- readme.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 642c2912e..8446d9133 100644 --- a/readme.md +++ b/readme.md @@ -518,7 +518,10 @@ This also accepts an `object` with the following fields to constrain the duratio - `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback). - `response` starts when the request has been written to the socket and ends when the response headers are received. - `send` starts when the socket is connected and ends with the request has been written to the socket. -- `request` starts when the request is initiated and ends when the response's end event fires. +- `request` starts when the request is initiated and ends when the response's `end` event fires. +- `read` starts when the `response` event is emitted and ends when the response's `end` event fires. + +**Note:** The `read` timeout is blocked by https://github.com/nodejs/node/issues/35923 ###### retry From 0920f1abd5e8b960de29006942a89b9832a639a3 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Fri, 26 Feb 2021 14:00:55 +0100 Subject: [PATCH 3/6] Failing --- test/timeout.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/timeout.ts b/test/timeout.ts index 4a3e33639..91f633bf7 100644 --- a/test/timeout.ts +++ b/test/timeout.ts @@ -643,7 +643,7 @@ test.serial('no unhandled `Premature close` error', withServer, async (t, server }); // TODO: use fakeTimers here -test.serial('`read` timeout - promise', withServer, async (t, server, got) => { +test.serial.failing('`read` timeout - promise', withServer, async (t, server, got) => { server.get('/', (_request, response) => { response.write('o'); }); @@ -657,7 +657,7 @@ test.serial('`read` timeout - promise', withServer, async (t, server, got) => { }); // TODO: use fakeTimers here -test.serial.only('`read` timeout - stream', withServer, async (t, server, got) => { +test.serial.failing('`read` timeout - stream', withServer, async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); From ad13db6597c7d2b5f61f8c61973da0f7dce09d9d Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Fri, 26 Feb 2021 15:35:24 +0100 Subject: [PATCH 4/6] Update readme.md Co-authored-by: Sindre Sorhus --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 8446d9133..5b7803cfe 100644 --- a/readme.md +++ b/readme.md @@ -519,7 +519,7 @@ This also accepts an `object` with the following fields to constrain the duratio - `response` starts when the request has been written to the socket and ends when the response headers are received. - `send` starts when the socket is connected and ends with the request has been written to the socket. - `request` starts when the request is initiated and ends when the response's `end` event fires. -- `read` starts when the `response` event is emitted and ends when the response's `end` event fires. +- ~~`read` starts when the `response` event is emitted and ends when the response's `end` event fires.~~ **Note:** The `read` timeout is blocked by https://github.com/nodejs/node/issues/35923 From bbb29013eb5a905cf73aa471ba3631c8a41af910 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Fri, 26 Feb 2021 15:35:30 +0100 Subject: [PATCH 5/6] Update source/core/utils/timed-out.ts Co-authored-by: Sindre Sorhus --- source/core/utils/timed-out.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/source/core/utils/timed-out.ts b/source/core/utils/timed-out.ts index 80d1d6d1f..8b4ddb167 100644 --- a/source/core/utils/timed-out.ts +++ b/source/core/utils/timed-out.ts @@ -19,7 +19,6 @@ export interface Delays { send?: number; response?: number; read?: number; - request?: number; } From cbe05e6e6e7362d800d876d6018ac3500f9e0aa7 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:30:28 +0100 Subject: [PATCH 6/6] fixes --- test/timeout.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/timeout.ts b/test/timeout.ts index 91f633bf7..a49f9f9dd 100644 --- a/test/timeout.ts +++ b/test/timeout.ts @@ -643,7 +643,7 @@ test.serial('no unhandled `Premature close` error', withServer, async (t, server }); // TODO: use fakeTimers here -test.serial.failing('`read` timeout - promise', withServer, async (t, server, got) => { +test.serial('`read` timeout - promise', withServer, async (t, server, got) => { server.get('/', (_request, response) => { response.write('o'); }); @@ -658,6 +658,8 @@ test.serial.failing('`read` timeout - promise', withServer, async (t, server, go // TODO: use fakeTimers here test.serial.failing('`read` timeout - stream', withServer, async (t, server, got) => { + t.timeout(100); + server.get('/', (_request, response) => { response.end('ok'); });