diff --git a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts index 74c7f161d..c9327b8e6 100644 --- a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts +++ b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts @@ -17,7 +17,11 @@ /** * Imports. */ -import { RequestThrottler, TalerErrorCode } from "@gnu-taler/taler-util"; +import { + Logger, + RequestThrottler, + TalerErrorCode, +} from "@gnu-taler/taler-util"; import { Headers, HttpRequestLibrary, @@ -41,6 +45,7 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { const requestMethod = options?.method ?? "GET"; const requestBody = options?.body; const requestHeader = options?.headers; + const requestTimeout = options?.timeout ?? { d_ms: 2 * 1000 }; if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) { const parsedUrl = new URL(requestUrl); @@ -70,26 +75,49 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { } } - const response = await fetch(requestUrl, { - headers: requestHeader, - body: myBody, - method: requestMethod, - // timeout: options?.timeout - }); + const controller = new AbortController(); + let timeoutId: any | undefined; + if (requestTimeout.d_ms !== "forever") { + timeoutId = setTimeout(() => { + controller.abort(TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT); + }, requestTimeout.d_ms); + } - const headerMap = new Headers(); - response.headers.forEach((value, key) => { - headerMap.set(key, value); - }); - return { - headers: headerMap, - status: response.status, - requestMethod, - requestUrl, - json: makeJsonHandler(response, requestUrl), - text: makeTextHandler(response, requestUrl), - bytes: async () => (await response.blob()).arrayBuffer(), - }; + try { + const response = await fetch(requestUrl, { + headers: requestHeader, + body: myBody, + method: requestMethod, + signal: controller.signal, + }); + + if (timeoutId) { + clearTimeout(timeoutId); + } + + const headerMap = new Headers(); + response.headers.forEach((value, key) => { + headerMap.set(key, value); + }); + return { + headers: headerMap, + status: response.status, + requestMethod, + requestUrl, + json: makeJsonHandler(response, requestUrl), + text: makeTextHandler(response, requestUrl), + bytes: async () => (await response.blob()).arrayBuffer(), + }; + } catch (e) { + if (controller.signal) { + throw TalerError.fromDetail( + controller.signal.reason, + {}, + `request to ${requestUrl} timed out`, + ); + } + throw e; + } } get(url: string, opt?: HttpRequestOptions): Promise {