gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet: throttle all http req


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet: throttle all http requests
Date: Tue, 08 Mar 2022 19:19:43 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 1d1c847b wallet: throttle all http requests
1d1c847b is described below

commit 1d1c847b793620acf3a2b193ab45eabf53234cb2
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Mar 8 19:19:29 2022 +0100

    wallet: throttle all http requests
    
    even from browsers / service workers
---
 .../util => taler-util/src}/RequestThrottler.ts    | 13 ++----
 packages/taler-util/src/index.ts                   |  1 +
 .../taler-wallet-core/src/headless/NodeHttpLib.ts  |  2 +-
 packages/taler-wallet-core/tsconfig.json           |  2 +-
 .../src/browserHttpLib.ts                          | 44 ++++++++++++++-----
 .../src/serviceWorkerHttpLib.ts                    | 51 ++++++++++++++--------
 6 files changed, 73 insertions(+), 40 deletions(-)

diff --git a/packages/taler-wallet-core/src/util/RequestThrottler.ts 
b/packages/taler-util/src/RequestThrottler.ts
similarity index 96%
rename from packages/taler-wallet-core/src/util/RequestThrottler.ts
rename to packages/taler-util/src/RequestThrottler.ts
index d79afe47..7689b421 100644
--- a/packages/taler-wallet-core/src/util/RequestThrottler.ts
+++ b/packages/taler-util/src/RequestThrottler.ts
@@ -14,20 +14,13 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { Logger } from "./logging.js";
+import { getTimestampNow, timestampCmp, timestampDifference } from "./time.js";
+
 /**
  * Implementation of token bucket throttling.
  */
 
-/**
- * Imports.
- */
-import {
-  getTimestampNow,
-  timestampDifference,
-  timestampCmp,
-  Logger,
-  URL,
-} from "@gnu-taler/taler-util";
 
 const logger = new Logger("RequestThrottler.ts");
 
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 0141be13..573b4a5c 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -30,3 +30,4 @@ export {
   secretbox_open,
   crypto_sign_keyPair_fromSeed,
 } from "./nacl-fast.js";
+export { RequestThrottler } from "./RequestThrottler.js";
diff --git a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts 
b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
index 5a90994b..2a8c9e36 100644
--- a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
+++ b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts
@@ -25,7 +25,7 @@ import {
   HttpRequestOptions,
   HttpResponse,
 } from "../util/http.js";
-import { RequestThrottler } from "../util/RequestThrottler.js";
+import { RequestThrottler } from "@gnu-taler/taler-util";
 import Axios, { AxiosResponse } from "axios";
 import { OperationFailedError, makeErrorDetails } from "../errors.js";
 import { Logger, bytesToString } from "@gnu-taler/taler-util";
diff --git a/packages/taler-wallet-core/tsconfig.json 
b/packages/taler-wallet-core/tsconfig.json
index 3da33236..c3366373 100644
--- a/packages/taler-wallet-core/tsconfig.json
+++ b/packages/taler-wallet-core/tsconfig.json
@@ -21,7 +21,7 @@
     "esModuleInterop": true,
     "importHelpers": true,
     "rootDir": "./src",
-    "typeRoots": ["./node_modules/@types"],
+    "typeRoots": ["./node_modules/@types"]
   },
   "references": [
     {
diff --git a/packages/taler-wallet-webextension/src/browserHttpLib.ts 
b/packages/taler-wallet-webextension/src/browserHttpLib.ts
index 63fd456f..8877edfc 100644
--- a/packages/taler-wallet-webextension/src/browserHttpLib.ts
+++ b/packages/taler-wallet-webextension/src/browserHttpLib.ts
@@ -24,7 +24,11 @@ import {
   HttpResponse,
   Headers,
 } from "@gnu-taler/taler-wallet-core";
-import { Logger, TalerErrorCode } from "@gnu-taler/taler-util";
+import {
+  Logger,
+  RequestThrottler,
+  TalerErrorCode,
+} from "@gnu-taler/taler-util";
 
 const logger = new Logger("browserHttpLib");
 
@@ -33,12 +37,32 @@ const logger = new Logger("browserHttpLib");
  * browser's XMLHttpRequest.
  */
 export class BrowserHttpLib implements HttpRequestLibrary {
-  fetch(url: string, options?: HttpRequestOptions): Promise<HttpResponse> {
-    const method = options?.method ?? "GET";
+  private throttle = new RequestThrottler();
+  private throttlingEnabled = true;
+
+  fetch(
+    requestUrl: string,
+    options?: HttpRequestOptions,
+  ): Promise<HttpResponse> {
+    const requestMethod = options?.method ?? "GET";
     let requestBody = options?.body;
+
+    if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) {
+      const parsedUrl = new URL(requestUrl);
+      throw OperationFailedError.fromCode(
+        TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
+        `request to origin ${parsedUrl.origin} was throttled`,
+        {
+          requestMethod,
+          requestUrl,
+          throttleStats: this.throttle.getThrottleStats(requestUrl),
+        },
+      );
+    }
+
     return new Promise<HttpResponse>((resolve, reject) => {
       const myRequest = new XMLHttpRequest();
-      myRequest.open(method, url);
+      myRequest.open(requestMethod, requestUrl);
       if (options?.headers) {
         for (const headerName in options.headers) {
           myRequest.setRequestHeader(headerName, options.headers[headerName]);
@@ -58,7 +82,7 @@ export class BrowserHttpLib implements HttpRequestLibrary {
             TalerErrorCode.WALLET_NETWORK_ERROR,
             "Could not make request",
             {
-              requestUrl: url,
+              requestUrl: requestUrl,
             },
           ),
         );
@@ -71,7 +95,7 @@ export class BrowserHttpLib implements HttpRequestLibrary {
               TalerErrorCode.WALLET_NETWORK_ERROR,
               "HTTP request failed (status 0, maybe URI scheme was wrong?)",
               {
-                requestUrl: url,
+                requestUrl: requestUrl,
               },
             );
             reject(exc);
@@ -92,7 +116,7 @@ export class BrowserHttpLib implements HttpRequestLibrary {
                 TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
                 "Invalid JSON from HTTP response",
                 {
-                  requestUrl: url,
+                  requestUrl: requestUrl,
                   httpStatusCode: myRequest.status,
                 },
               );
@@ -102,7 +126,7 @@ export class BrowserHttpLib implements HttpRequestLibrary {
                 TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
                 "Invalid JSON from HTTP response",
                 {
-                  requestUrl: url,
+                  requestUrl: requestUrl,
                   httpStatusCode: myRequest.status,
                 },
               );
@@ -126,10 +150,10 @@ export class BrowserHttpLib implements HttpRequestLibrary 
{
             headerMap.set(headerName, value);
           });
           const resp: HttpResponse = {
-            requestUrl: url,
+            requestUrl: requestUrl,
             status: myRequest.status,
             headers: headerMap,
-            requestMethod: method,
+            requestMethod: requestMethod,
             json: makeJson,
             text: makeText,
             bytes: async () => myRequest.response,
diff --git a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts 
b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts
index a66d4e09..6f2585c1 100644
--- a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts
+++ b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts
@@ -17,37 +17,55 @@
 /**
  * Imports.
  */
-import { Logger, TalerErrorCode } from "@gnu-taler/taler-util";
+import { RequestThrottler, TalerErrorCode } from "@gnu-taler/taler-util";
 import {
-  Headers, HttpRequestLibrary,
+  Headers,
+  HttpRequestLibrary,
   HttpRequestOptions,
   HttpResponse,
-  OperationFailedError
+  OperationFailedError,
 } from "@gnu-taler/taler-wallet-core";
 
-const logger = new Logger("browserHttpLib");
-
 /**
  * An implementation of the [[HttpRequestLibrary]] using the
  * browser's XMLHttpRequest.
  */
 export class ServiceWorkerHttpLib implements HttpRequestLibrary {
-  async fetch(requestUrl: string, options?: HttpRequestOptions): 
Promise<HttpResponse> {
+  private throttle = new RequestThrottler();
+  private throttlingEnabled = true;
+
+  async fetch(
+    requestUrl: string,
+    options?: HttpRequestOptions,
+  ): Promise<HttpResponse> {
     const requestMethod = options?.method ?? "GET";
     const requestBody = options?.body;
     const requestHeader = options?.headers;
 
+    if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) {
+      const parsedUrl = new URL(requestUrl);
+      throw OperationFailedError.fromCode(
+        TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
+        `request to origin ${parsedUrl.origin} was throttled`,
+        {
+          requestMethod,
+          requestUrl,
+          throttleStats: this.throttle.getThrottleStats(requestUrl),
+        },
+      );
+    }
+
     const response = await fetch(requestUrl, {
       headers: requestHeader,
       body: requestBody,
       method: requestMethod,
       // timeout: options?.timeout
-    })
+    });
 
     const headerMap = new Headers();
     response.headers.forEach((value, key) => {
       headerMap.set(key, value);
-    })
+    });
     return {
       headers: headerMap,
       status: response.status,
@@ -56,11 +74,9 @@ export class ServiceWorkerHttpLib implements 
HttpRequestLibrary {
       json: makeJsonHandler(response, requestUrl),
       text: makeTextHandler(response, requestUrl),
       bytes: async () => (await response.blob()).arrayBuffer(),
-    }
-
+    };
   }
 
-
   get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
     return this.fetch(url, {
       method: "GET",
@@ -89,7 +105,7 @@ function makeTextHandler(response: Response, requestUrl: 
string) {
   return async function getJsonFromResponse(): Promise<any> {
     let respText;
     try {
-      respText = await response.text()
+      respText = await response.text();
     } catch (e) {
       throw OperationFailedError.fromCode(
         TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
@@ -100,15 +116,15 @@ function makeTextHandler(response: Response, requestUrl: 
string) {
         },
       );
     }
-    return respText
-  }
+    return respText;
+  };
 }
 
 function makeJsonHandler(response: Response, requestUrl: string) {
   return async function getJsonFromResponse(): Promise<any> {
     let responseJson;
     try {
-      responseJson = await response.json()
+      responseJson = await response.json();
     } catch (e) {
       throw OperationFailedError.fromCode(
         TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
@@ -129,7 +145,6 @@ function makeJsonHandler(response: Response, requestUrl: 
string) {
         },
       );
     }
-    return responseJson
-  }
+    return responseJson;
+  };
 }
-

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]