diff options
Diffstat (limited to 'packages/taler-wallet-cli/src/harness/faultInjection.ts')
-rw-r--r-- | packages/taler-wallet-cli/src/harness/faultInjection.ts | 256 |
1 files changed, 0 insertions, 256 deletions
diff --git a/packages/taler-wallet-cli/src/harness/faultInjection.ts b/packages/taler-wallet-cli/src/harness/faultInjection.ts deleted file mode 100644 index 4c3d0c123..000000000 --- a/packages/taler-wallet-cli/src/harness/faultInjection.ts +++ /dev/null @@ -1,256 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2020 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 <http://www.gnu.org/licenses/> - */ - -/** - * Fault injection proxy. - * - * @author Florian Dold <dold@taler.net> - */ - -/** - * Imports - */ -import * as http from "http"; -import { URL } from "url"; -import { - GlobalTestState, - ExchangeService, - ExchangeServiceInterface, - MerchantServiceInterface, - MerchantService, -} from "../harness/harness.js"; - -export interface FaultProxyConfig { - inboundPort: number; - targetPort: number; -} - -/** - * Fault injection context. Modified by fault injection functions. - */ -export interface FaultInjectionRequestContext { - requestUrl: string; - method: string; - requestHeaders: Record<string, string | string[] | undefined>; - requestBody?: Buffer; - dropRequest: boolean; -} - -export interface FaultInjectionResponseContext { - request: FaultInjectionRequestContext; - statusCode: number; - responseHeaders: Record<string, string | string[] | undefined>; - responseBody: Buffer | undefined; - dropResponse: boolean; -} - -export interface FaultSpec { - modifyRequest?: (ctx: FaultInjectionRequestContext) => Promise<void>; - modifyResponse?: (ctx: FaultInjectionResponseContext) => Promise<void>; -} - -export class FaultProxy { - constructor( - private globalTestState: GlobalTestState, - private faultProxyConfig: FaultProxyConfig, - ) {} - - private currentFaultSpecs: FaultSpec[] = []; - - start() { - const server = http.createServer((req, res) => { - const requestChunks: Buffer[] = []; - const requestUrl = `http://localhost:${this.faultProxyConfig.inboundPort}${req.url}`; - console.log("request for", new URL(requestUrl)); - req.on("data", (chunk) => { - requestChunks.push(chunk); - }); - req.on("end", async () => { - console.log("end of data"); - let requestBuffer: Buffer | undefined; - if (requestChunks.length > 0) { - requestBuffer = Buffer.concat(requestChunks); - } - console.log("full request body", requestBuffer); - - const faultReqContext: FaultInjectionRequestContext = { - dropRequest: false, - method: req.method!!, - requestHeaders: req.headers, - requestUrl, - requestBody: requestBuffer, - }; - - for (const faultSpec of this.currentFaultSpecs) { - if (faultSpec.modifyRequest) { - await faultSpec.modifyRequest(faultReqContext); - } - } - - if (faultReqContext.dropRequest) { - res.destroy(); - return; - } - - const faultedUrl = new URL(faultReqContext.requestUrl); - - const proxyRequest = http.request({ - method: faultReqContext.method, - host: "localhost", - port: this.faultProxyConfig.targetPort, - path: faultedUrl.pathname + faultedUrl.search, - headers: faultReqContext.requestHeaders, - }); - - console.log( - `proxying request to target path '${ - faultedUrl.pathname + faultedUrl.search - }'`, - ); - - if (faultReqContext.requestBody) { - proxyRequest.write(faultReqContext.requestBody); - } - proxyRequest.end(); - proxyRequest.on("response", (proxyResp) => { - console.log("gotten response from target", proxyResp.statusCode); - const respChunks: Buffer[] = []; - proxyResp.on("data", (proxyRespData) => { - respChunks.push(proxyRespData); - }); - proxyResp.on("end", async () => { - console.log("end of target response"); - let responseBuffer: Buffer | undefined; - if (respChunks.length > 0) { - responseBuffer = Buffer.concat(respChunks); - } - const faultRespContext: FaultInjectionResponseContext = { - request: faultReqContext, - dropResponse: false, - responseBody: responseBuffer, - responseHeaders: proxyResp.headers, - statusCode: proxyResp.statusCode!!, - }; - for (const faultSpec of this.currentFaultSpecs) { - const modResponse = faultSpec.modifyResponse; - if (modResponse) { - await modResponse(faultRespContext); - } - } - if (faultRespContext.dropResponse) { - req.destroy(); - return; - } - if (faultRespContext.responseBody) { - // We must accommodate for potentially changed content length - faultRespContext.responseHeaders[ - "content-length" - ] = `${faultRespContext.responseBody.byteLength}`; - } - console.log("writing response head"); - res.writeHead( - faultRespContext.statusCode, - http.STATUS_CODES[faultRespContext.statusCode], - faultRespContext.responseHeaders, - ); - if (faultRespContext.responseBody) { - res.write(faultRespContext.responseBody); - } - res.end(); - }); - }); - }); - }); - - server.listen(this.faultProxyConfig.inboundPort); - this.globalTestState.servers.push(server); - } - - addFault(f: FaultSpec) { - this.currentFaultSpecs.push(f); - } - - clearAllFaults() { - this.currentFaultSpecs = []; - } -} - -export class FaultInjectedExchangeService implements ExchangeServiceInterface { - baseUrl: string; - port: number; - faultProxy: FaultProxy; - - get name(): string { - return this.innerExchange.name; - } - - get masterPub(): string { - return this.innerExchange.masterPub; - } - - private innerExchange: ExchangeService; - - constructor( - t: GlobalTestState, - e: ExchangeService, - proxyInboundPort: number, - ) { - this.innerExchange = e; - this.faultProxy = new FaultProxy(t, { - inboundPort: proxyInboundPort, - targetPort: e.port, - }); - this.faultProxy.start(); - - const exchangeUrl = new URL(e.baseUrl); - exchangeUrl.port = `${proxyInboundPort}`; - this.baseUrl = exchangeUrl.href; - this.port = proxyInboundPort; - } -} - -export class FaultInjectedMerchantService implements MerchantServiceInterface { - baseUrl: string; - port: number; - faultProxy: FaultProxy; - - get name(): string { - return this.innerMerchant.name; - } - - private innerMerchant: MerchantService; - private inboundPort: number; - - constructor( - t: GlobalTestState, - m: MerchantService, - proxyInboundPort: number, - ) { - this.innerMerchant = m; - this.faultProxy = new FaultProxy(t, { - inboundPort: proxyInboundPort, - targetPort: m.port, - }); - this.faultProxy.start(); - this.inboundPort = proxyInboundPort; - } - - makeInstanceBaseUrl(instanceName?: string | undefined): string { - const url = new URL(this.innerMerchant.makeInstanceBaseUrl(instanceName)); - url.port = `${this.inboundPort}`; - return url.href; - } -} |