From 2a4510aa0de3446ad141f4bdea36935cdf9a5ecb Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Fri, 26 Mar 2021 20:17:50 +0300 Subject: [PATCH] Replacing node-fetch with cross-fetch (#687) * installing cross-fetch * implementing cross-fetch * Correcting web3 dependancy * importing types from cross-fetch * fixing dependancies * adding imports from cross/fetch/lib * changing .buffer() to .arrayBufer() * implementing timeout-signal * chaning require statements to import statements * fixing require/import issues * using default import for timeoutSignal * fixing linting issues * fixing dependancy issue * lint fix * fix timeout Signed-off-by: mihaisc * add abort controller compatible with browser and node Signed-off-by: mihaisc Co-authored-by: mihaisc --- package-lock.json | 61 +++++++++++++------ package.json | 9 +-- src/ocean/utils/WebServiceConnector.ts | 22 +++---- src/provider/Provider.ts | 4 -- src/utils/Timeout.ts | 17 ++++++ .../__mocks__/WebServiceConnector.mock.ts | 2 +- 6 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 src/utils/Timeout.ts diff --git a/package-lock.json b/package-lock.json index f915d4aa3..d15b6b428 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1852,6 +1852,16 @@ "json-rpc-engine": "^5.1.3" }, "dependencies": { + "cross-fetch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", + "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", + "dev": true, + "requires": { + "node-fetch": "2.1.2", + "whatwg-fetch": "2.0.4" + } + }, "eth-json-rpc-errors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.1.tgz", @@ -1860,6 +1870,12 @@ "requires": { "fast-safe-stringify": "^2.0.6" } + }, + "node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", + "dev": true } } }, @@ -2002,6 +2018,16 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, + "cross-fetch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", + "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", + "dev": true, + "requires": { + "node-fetch": "2.1.2", + "whatwg-fetch": "2.0.4" + } + }, "ethereum-common": { "version": "0.0.18", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", @@ -2033,6 +2059,12 @@ "safe-buffer": "^5.1.1" } }, + "node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", + "dev": true + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2157,9 +2189,9 @@ }, "dependencies": { "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -3746,21 +3778,11 @@ } }, "cross-fetch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", - "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", - "dev": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.2.tgz", + "integrity": "sha512-+JhD65rDNqLbGmB3Gzs3HrEKC0aQnD+XA3SY6RjgkF88jV2q5cTc5+CwxlS3sdmLk98gpPt5CF9XRnPdlxZe6w==", "requires": { - "node-fetch": "2.1.2", - "whatwg-fetch": "2.0.4" - }, - "dependencies": { - "node-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", - "dev": true - } + "node-fetch": "2.6.1" } }, "cross-spawn": { @@ -8278,6 +8300,11 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-abort-controller": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-1.2.0.tgz", + "integrity": "sha512-x6Pv6ACfOUmYGDW/SRjSKBJs7waJRxRPQ9FeXFqfBtEtvJQBfuPl5P74p0Ow+vl0w6WURvXwn+xq/3S95Z7e5Q==" + }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", diff --git a/package.json b/package.json index f9ec5d5e0..d207415ea 100644 --- a/package.json +++ b/package.json @@ -38,17 +38,18 @@ }, "homepage": "https://github.com/oceanprotocol/ocean.js#readme", "peerDependencies": { - "web3": "^1.2.3" + "web3": "^1.3.4" }, "dependencies": { "@ethereum-navigator/navigator": "^0.5.2", "@oceanprotocol/contracts": "^0.5.10", "@types/crypto-js": "^4.0.1", + "cross-fetch": "^3.1.2", "crypto-js": "^4.0.0", "decimal.js": "^10.2.1", "fs": "0.0.1-security", "lzma": "^2.3.2", - "node-fetch": "^2.6.1", + "node-abort-controller": "^1.2.0", "save-file": "^2.3.1", "uuid": "^8.3.2", "web3": "^1.3.4", @@ -60,8 +61,8 @@ "@types/chai": "^4.2.11", "@types/chai-spies": "^1.0.1", "@types/mocha": "^8.0.3", - "@types/node": "^14.14.20", - "@types/node-fetch": "^2.5.5", + "@types/node": "^14.14.35", + "@types/node-fetch": "^2.5.8", "@typescript-eslint/eslint-plugin": "^4.13.0", "@typescript-eslint/parser": "^4.13.0", "auto-changelog": "^2.2.1", diff --git a/src/ocean/utils/WebServiceConnector.ts b/src/ocean/utils/WebServiceConnector.ts index 6c78df312..23e58bf73 100644 --- a/src/ocean/utils/WebServiceConnector.ts +++ b/src/ocean/utils/WebServiceConnector.ts @@ -1,11 +1,9 @@ -import { BodyInit, RequestInit, Response } from 'node-fetch' +import { Response } from 'node-fetch' import fs from 'fs' import { Logger } from '../../utils' import save from 'save-file' -// import { createWriteStream } from 'streamsaver' - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const fetch = require('node-fetch') +import timeoutSignal from '../../utils/Timeout' +const fetch = require('cross-fetch') /** * Provides a common interface to web services. @@ -40,12 +38,12 @@ export class WebServiceConnector { method: 'POST', body: payload, headers, - timeout: 5000 + signal: timeoutSignal(5000) }) } else { return this.fetch(url, { method: 'POST', - timeout: 5000 + signal: timeoutSignal(5000) }) } } @@ -56,7 +54,7 @@ export class WebServiceConnector { headers: { 'Content-type': 'application/json' }, - timeout: 5000 + signal: timeoutSignal(5000) }) } @@ -68,7 +66,7 @@ export class WebServiceConnector { headers: { 'Content-type': 'application/json' }, - timeout: 5000 + signal: timeoutSignal(5000) }) } else { return this.fetch(url, { @@ -76,7 +74,7 @@ export class WebServiceConnector { headers: { 'Content-type': 'application/json' }, - timeout: 5000 + signal: timeoutSignal(5000) }) } } @@ -89,7 +87,7 @@ export class WebServiceConnector { headers: { 'Content-type': 'application/json' }, - timeout: 5000 + signal: timeoutSignal(5000) }) } else { return this.fetch(url, { @@ -97,7 +95,7 @@ export class WebServiceConnector { headers: { 'Content-type': 'application/json' }, - timeout: 5000 + signal: timeoutSignal(5000) }) } } diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 437614433..af4896dba 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -7,13 +7,9 @@ import { ComputeInput } from '../ocean/interfaces/ComputeInput' import { Output } from '../ocean/interfaces/ComputeOutput' import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm' import { Versions } from '../ocean/Versions' -import { Response } from 'node-fetch' import { DDO } from '../ddo/DDO' import DID from '../ocean/DID' -// eslint-disable-next-line @typescript-eslint/no-var-requires -const fetch = require('node-fetch') - export interface ServiceEndpoint { serviceName: string method: string diff --git a/src/utils/Timeout.ts b/src/utils/Timeout.ts new file mode 100644 index 000000000..f8229ee37 --- /dev/null +++ b/src/utils/Timeout.ts @@ -0,0 +1,17 @@ +import AbortController from 'node-abort-controller' + +export default function timeoutSignal(timeout: number) { + if (!Number.isInteger(timeout)) { + throw new TypeError(`Expected an integer, got ${typeof timeout}`) + } + const signalMap = new WeakMap() + const controller = new AbortController() + + const timeoutId = setTimeout(() => { + controller.abort() + }, timeout) + + signalMap.set(controller.signal, timeoutId) + // any is needed due to some type incompatibility + return controller.signal as any +} diff --git a/test/unit/__mocks__/WebServiceConnector.mock.ts b/test/unit/__mocks__/WebServiceConnector.mock.ts index 8a96f6916..90a282839 100644 --- a/test/unit/__mocks__/WebServiceConnector.mock.ts +++ b/test/unit/__mocks__/WebServiceConnector.mock.ts @@ -1,5 +1,5 @@ import { WebServiceConnector } from '../../../src/ocean/utils/WebServiceConnector' -import { RequestInit } from 'node-fetch' +import { RequestInit } from 'cross-fetch/lib.fetch' export default class WebServiceConnectorMock extends (WebServiceConnector as any) { constructor(private returnData: any) {