Skip to content

Commit

Permalink
Fixed broken fetch for Node.js > 18.x and fixed double callback (#6381)
Browse files Browse the repository at this point in the history
* web3-providers-http: Fixed broken fetch for Node.js > 18.x and fixed double callback

* web3-providers-http: Append globalThis.fetch for tests

* web3-providers-http: Bump deps version
  • Loading branch information
kaliubuntu0206 authored Aug 26, 2023
1 parent 3e685bf commit 9e063ef
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -693,3 +693,7 @@ Released with 1.0.0-beta.37 code base.


## [Unreleased]

### Fixed

- Fixed broken fetch for Node.js > 18.x and fixed double callback (#6381)
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"core-js": "^3.6.5",
"cross-fetch": "^4.0.0",
"crypto-browserify": "^3.12.0",
"crypto-js": "^3.3.0",
"decache": "^4.6.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/web3-providers-http/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"types": "types/index.d.ts",
"main": "lib/index.js",
"dependencies": {
"abortcontroller-polyfill": "^1.7.3",
"cross-fetch": "^3.1.4",
"abortcontroller-polyfill": "^1.7.5",
"cross-fetch": "^4.0.0",
"es6-promise": "^4.2.8",
"web3-core-helpers": "1.10.1"
},
Expand Down
38 changes: 27 additions & 11 deletions packages/web3-providers-http/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@
*/

var errors = require('web3-core-helpers').errors;
var fetch = require('cross-fetch');
var http = require('http');
var https = require('https');

// Apply missing polyfill for IE
require('cross-fetch/polyfill');
require('es6-promise').polyfill();

// import abortController if abortController is not included in node
if(typeof global !== "undefined" && !global.AbortController){
require('abortcontroller-polyfill/dist/polyfill-patch-fetch')
require('abortcontroller-polyfill/dist/polyfill-patch-fetch');
}

/**
Expand All @@ -46,6 +46,7 @@ var HttpProvider = function HttpProvider(host, options) {
this.timeout = options.timeout || 0;
this.headers = options.headers;
this.agent = options.agent;
this.forceGlobalFetch = options.forceGlobalFetch || false;
this.connected = false;

// keepAlive is true unless explicitly set to false
Expand Down Expand Up @@ -74,6 +75,7 @@ HttpProvider.prototype.send = function (payload, callback) {
};
var headers = {};
var controller;
var fetchFunc = this.forceGlobalFetch ? globalThis.fetch : fetch;

if (typeof AbortController !== 'undefined') {
controller = new AbortController();
Expand Down Expand Up @@ -138,11 +140,25 @@ HttpProvider.prototype.send = function (payload, callback) {
}

// Response is a stream data so should be awaited for json response
response.json().then(function (data) {
callback(null, data);
}).catch(function (error) {
callback(errors.InvalidResponse(response));
});
response
.json()
.then(
function (data) {
callback(null, data);
},
function () {
response
.text()
.then(
function (text) {
callback(errors.InvalidResponse(text));
},
function () {
callback(errors.InvalidResponse(""));
}
);
}
);
};

var failed = function (error) {
Expand All @@ -152,14 +168,14 @@ HttpProvider.prototype.send = function (payload, callback) {

if (error.name === 'AbortError') {
callback(errors.ConnectionTimeout(this.timeout));
return;
}

callback(errors.InvalidConnection(this.host, error));
}
};

fetch(this.host, options)
.then(success.bind(this))
.catch(failed.bind(this));
fetchFunc(this.host, options)
.then(success.bind(this), failed.bind(this));
};

HttpProvider.prototype.disconnect = function () {
Expand Down
1 change: 1 addition & 0 deletions packages/web3-providers-http/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export class HttpProvider extends HttpProviderBase {
timeout: number;
headers?: HttpHeader[];
agent?: HttpProviderAgent;
forceGlobalFetch?: boolean;
connected: boolean;

constructor(host?: string, options?: HttpProviderOptions);
Expand Down
11 changes: 6 additions & 5 deletions test/httpprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ var http = require('http');
var https = require('https');
var Web3 = require('../packages/web3');
var HttpProvider = require('../packages/web3-providers-http');
// Mock test with globalThis.fetch func
var fetchMock = require('fetch-mock');
require('cross-fetch/polyfill');

function isObject(object) {
return object != null && typeof object === 'object';
Expand Down Expand Up @@ -72,15 +74,14 @@ describe('web3-providers-http', function () {
describe('send', function () {
it('should fail with invalid remote node connection', async function () {

var provider = new HttpProvider('http://localhost:8545');
var provider = new HttpProvider('http://localhost:8545', { forceGlobalFetch: true });
var web3 = new Web3(provider);

await expect(web3.eth.getChainId()).to.be.rejectedWith(Error, "CONNECTION ERROR: Couldn't connect to node http://localhost:8545.");

});

it('should fail for non-json format response', async function () {
var provider = new HttpProvider('/fetchMock');
var provider = new HttpProvider('/fetchMock', { forceGlobalFetch: true });
var web3 = new Web3(provider);

fetchMock.mock('/fetchMock', 'Testing non-json format response');
Expand All @@ -90,7 +91,7 @@ describe('web3-providers-http', function () {
});

it('should timeout by delayed response', async function () {
var provider = new HttpProvider('/fetchMock', { timeout: 500 });
var provider = new HttpProvider('/fetchMock', { forceGlobalFetch: true, timeout: 500 });
var web3 = new Web3(provider);

fetchMock.mock('/fetchMock', 'Testing non-json format response', { delay: 1000 });
Expand All @@ -100,7 +101,7 @@ describe('web3-providers-http', function () {
});

it('should send basic async request', async function () {
var provider = new HttpProvider('/fetchMock');
var provider = new HttpProvider('/fetchMock', { forceGlobalFetch: true });

var reqObject = {
'jsonrpc': '2.0',
Expand Down

0 comments on commit 9e063ef

Please sign in to comment.