diff options
Diffstat (limited to 'packages/web-util/src/utils/http-impl.sw.ts')
-rw-r--r-- | packages/web-util/src/utils/http-impl.sw.ts | 85 |
1 files changed, 46 insertions, 39 deletions
diff --git a/packages/web-util/src/utils/http-impl.sw.ts b/packages/web-util/src/utils/http-impl.sw.ts index 3120309f4..9c820bb4b 100644 --- a/packages/web-util/src/utils/http-impl.sw.ts +++ b/packages/web-util/src/utils/http-impl.sw.ts @@ -18,15 +18,16 @@ * Imports. */ import { + Duration, RequestThrottler, - TalerErrorCode, TalerError, - Duration, + TalerErrorCode } from "@gnu-taler/taler-util"; import { DEFAULT_REQUEST_TIMEOUT_MS, Headers, + HttpLibArgs, HttpRequestLibrary, HttpRequestOptions, HttpResponse, @@ -38,9 +39,15 @@ import { * An implementation of the [[HttpRequestLibrary]] using the * browser's XMLHttpRequest. */ -export class ServiceWorkerHttpLib implements HttpRequestLibrary { +export class BrowserFetchHttpLib implements HttpRequestLibrary { private throttle = new RequestThrottler(); private throttlingEnabled = true; + private requireTls = false; + + public constructor(args?: HttpLibArgs) { + this.throttlingEnabled = args?.enableThrottling ?? true; + this.requireTls = args?.requireTls ?? false; + } async fetch( requestUrl: string, @@ -51,9 +58,11 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { const requestHeader = options?.headers; const requestTimeout = options?.timeout ?? Duration.fromMilliseconds(DEFAULT_REQUEST_TIMEOUT_MS); + const requestCancel = options?.cancellationToken; + const requestRedirect = options?.redirect; + const parsedUrl = new URL(requestUrl); if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) { - const parsedUrl = new URL(requestUrl); throw TalerError.fromDetail( TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED, { @@ -64,22 +73,42 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { `request to origin ${parsedUrl.origin} was throttled`, ); } + if (this.requireTls && parsedUrl.protocol !== "https:") { + throw TalerError.fromDetail( + TalerErrorCode.WALLET_NETWORK_ERROR, + { + requestMethod: requestMethod, + requestUrl: requestUrl, + }, + `request to ${parsedUrl.origin} is not possible with protocol ${parsedUrl.protocol}`, + ); + } - let myBody: ArrayBuffer | undefined = - requestMethod === "POST" ? encodeBody(requestBody) : undefined; - - const requestHeadersMap = { - ...getDefaultHeaders(requestMethod), - ...requestHeader, - }; + const myBody: ArrayBuffer | undefined = + requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH" + ? encodeBody(requestBody) + : undefined; + + const requestHeadersMap = getDefaultHeaders(requestMethod); + if (requestHeader) { + Object.entries(requestHeader).forEach(([key, value]) => { + if (value === undefined) return; + requestHeadersMap[key] = value + }) + } const controller = new AbortController(); - let timeoutId: any | undefined; + let timeoutId: ReturnType<typeof setTimeout> | undefined; if (requestTimeout.d_ms !== "forever") { timeoutId = setTimeout(() => { - controller.abort(TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT); + controller.abort(TalerErrorCode.GENERIC_TIMEOUT); }, requestTimeout.d_ms); } + if (requestCancel) { + requestCancel.onCancelled(() => { + controller.abort(TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR) + }); + } try { const response = await fetch(requestUrl, { @@ -87,6 +116,7 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { body: myBody, method: requestMethod, signal: controller.signal, + redirect: requestRedirect }); if (timeoutId) { @@ -109,42 +139,19 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { } catch (e) { if (controller.signal) { throw TalerError.fromDetail( - TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT, + controller.signal.reason, { requestUrl, requestMethod, timeoutMs: requestTimeout.d_ms === "forever" ? 0 : requestTimeout.d_ms }, - `request to ${requestUrl} timed out`, + `HTTP request failed.`, ); } throw e; } } - get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> { - return this.fetch(url, { - method: "GET", - ...opt, - }); - } - - postJson( - url: string, - body: any, - opt?: HttpRequestOptions, - ): Promise<HttpResponse> { - return this.fetch(url, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - ...opt, - }); - } - - stop(): void { - // Nothing to do - } } function makeTextHandler( @@ -190,7 +197,7 @@ function makeJsonHandler( requestMethod, httpStatusCode: response.status, }, - message, + message, ); } } |