From ffd2a62c3f7df94365980302fef3bc3376b48182 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 3 Aug 2020 13:00:48 +0530 Subject: modularize repo, use pnpm, improve typechecking --- .../taler-wallet-core/src/headless/NodeHttpLib.ts | 133 +++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 packages/taler-wallet-core/src/headless/NodeHttpLib.ts (limited to 'packages/taler-wallet-core/src/headless/NodeHttpLib.ts') diff --git a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts new file mode 100644 index 000000000..d109c3b7c --- /dev/null +++ b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts @@ -0,0 +1,133 @@ +/* + This file is part of GNU Taler + (C) 2019 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + + SPDX-License-Identifier: AGPL3.0-or-later +*/ + +/** + * Imports. + */ +import { + Headers, + HttpRequestLibrary, + HttpRequestOptions, + HttpResponse, +} from "../util/http"; +import { RequestThrottler } from "../util/RequestThrottler"; +import Axios from "axios"; +import { OperationFailedError, makeErrorDetails } from "../operations/errors"; +import { TalerErrorCode } from "../TalerErrorCode"; + +/** + * Implementation of the HTTP request library interface for node. + */ +export class NodeHttpLib implements HttpRequestLibrary { + private throttle = new RequestThrottler(); + private throttlingEnabled = true; + + /** + * Set whether requests should be throttled. + */ + setThrottling(enabled: boolean): void { + this.throttlingEnabled = enabled; + } + + private async req( + method: "post" | "get", + url: string, + body: any, + opt?: HttpRequestOptions, + ): Promise { + if (this.throttlingEnabled && this.throttle.applyThrottle(url)) { + throw Error("request throttled"); + } + const resp = await Axios({ + method, + url: url, + responseType: "text", + headers: opt?.headers, + validateStatus: () => true, + transformResponse: (x) => x, + data: body, + }); + + const respText = resp.data; + if (typeof respText !== "string") { + throw new OperationFailedError( + makeErrorDetails( + TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, + "unexpected response type", + { + httpStatusCode: resp.status, + requestUrl: url, + }, + ), + ); + } + const makeJson = async (): Promise => { + let responseJson; + try { + responseJson = JSON.parse(respText); + } catch (e) { + throw new OperationFailedError( + makeErrorDetails( + TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, + "invalid JSON", + { + httpStatusCode: resp.status, + requestUrl: url, + }, + ), + ); + } + if (responseJson === null || typeof responseJson !== "object") { + throw new OperationFailedError( + makeErrorDetails( + TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, + "invalid JSON", + { + httpStatusCode: resp.status, + requestUrl: url, + }, + ), + ); + } + return responseJson; + }; + const headers = new Headers(); + for (const hn of Object.keys(resp.headers)) { + headers.set(hn, resp.headers[hn]); + } + return { + requestUrl: url, + headers, + status: resp.status, + text: async () => resp.data, + json: makeJson, + }; + } + + async get(url: string, opt?: HttpRequestOptions): Promise { + return this.req("get", url, undefined, opt); + } + + async postJson( + url: string, + body: any, + opt?: HttpRequestOptions, + ): Promise { + return this.req("post", url, body, opt); + } +} -- cgit v1.2.3