summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-15 23:51:35 +0100
committerFlorian Dold <florian@dold.me>2024-02-15 23:51:35 +0100
commit490ef893e04d0515c3093a5a3e1cf14e707f3ea6 (patch)
treebe356738aa4ae4d577e24d1c6a6e7b70a2d20501
parent42a7a31fb2f10c7d3049d35dec331ed4237cc882 (diff)
downloadwallet-core-490ef893e04d0515c3093a5a3e1cf14e707f3ea6.tar.gz
wallet-core-490ef893e04d0515c3093a5a3e1cf14e707f3ea6.tar.bz2
wallet-core-490ef893e04d0515c3093a5a3e1cf14e707f3ea6.zip
taler-util: cancellation and timeouts on NodeJS
-rw-r--r--packages/taler-util/src/http-impl.node.ts52
1 files 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
index 5e613e6cd..ea2309504 100644
--- 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);
});