taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 490ef893e04d0515c3093a5a3e1cf14e707f3ea6
parent 42a7a31fb2f10c7d3049d35dec331ed4237cc882
Author: Florian Dold <florian@dold.me>
Date:   Thu, 15 Feb 2024 23:51:35 +0100

taler-util: cancellation and timeouts on NodeJS

Diffstat:
Mpackages/taler-util/src/http-impl.node.ts | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+), 0 deletions(-)

diff --git a/packages/taler-util/src/http-impl.node.ts b/packages/taler-util/src/http-impl.node.ts @@ -184,6 +184,18 @@ export class HttpLibImpl implements HttpRequestLibrary { ); } + let timeoutHandle: NodeJS.Timer | undefined = undefined; + let cancelCancelledHandler: (() => void) | undefined = undefined; + + const doCleanup = () => { + if (timeoutHandle != null) { + clearTimeout(timeoutHandle); + } + if (cancelCancelledHandler) { + cancelCancelledHandler(); + } + }; + return new Promise((resolve, reject) => { const handler = (res: IncomingMessage) => { res.on("data", (d) => { @@ -219,6 +231,7 @@ export class HttpLibImpl implements HttpRequestLibrary { return text; }, }; + doCleanup(); resolve(resp); }); res.on("error", (e) => { @@ -232,6 +245,7 @@ export class HttpLibImpl implements HttpRequestLibrary { }, `Error in HTTP response handler: ${code}`, ); + doCleanup(); reject(err); }); }; @@ -245,6 +259,43 @@ export class HttpLibImpl implements HttpRequestLibrary { throw new Error(`unsupported protocol ${options.protocol}`); } + if (timeoutMs != null) { + timeoutHandle = setTimeout(() => { + logger.info(`request to ${url} timed out`); + const err = TalerError.fromDetail( + TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR, + { + requestUrl: url, + requestMethod: method, + httpStatusCode: 0, + }, + `Request timed out after ${timeoutMs} ms`, + ); + timeoutHandle = undefined; + req.destroy(); + doCleanup(); + reject(err); + req.destroy(); + }, timeoutMs); + } + + if (opt?.cancellationToken) { + cancelCancelledHandler = opt.cancellationToken.onCancelled(() => { + const err = TalerError.fromDetail( + TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR, + { + requestUrl: url, + requestMethod: method, + httpStatusCode: 0, + }, + `Request cancelled`, + ); + req.destroy(); + doCleanup(); + reject(err); + }); + } + req.on("error", (e: Error) => { const code = "code" in e ? e.code : "unknown"; const err = TalerError.fromDetail( @@ -256,6 +307,7 @@ export class HttpLibImpl implements HttpRequestLibrary { }, `Error in HTTP request: ${code}`, ); + doCleanup(); reject(err); });