Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for custom http agent #2980

Merged
merged 11 commits into from
Jan 8, 2020
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Released with 1.0.0-beta.37 code base.
- Revert instruction handling added which can get activated with the ``handleRevert`` module property (#3248)
- The ``receipt`` does now exist as property on the error object for transaction related errors (#3259)
- ``internalType`` added to ``AbiInput`` TS interface in ``web3-utils`` (#3279)
- Agent option added to the ``HttpProvider`` options (#2980)

### Changed

Expand Down
9 changes: 9 additions & 0 deletions packages/web3-core-helpers/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/

import * as net from 'net';
import * as http from 'http';
import * as https from 'https';

export class formatters {
static outputBigNumberFormatter(number: number): number;
Expand Down Expand Up @@ -158,6 +160,13 @@ export interface HttpProviderOptions {
timeout?: number;
headers?: HttpHeader[];
withCredentials?: boolean;
agent?: HttpAgent
}

export interface HttpAgent {
http?: http.Agent;
https?: https.Agent;
baseUrl?: string;
}

export interface HttpHeader {
Expand Down
9 changes: 7 additions & 2 deletions packages/web3-providers-http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ This will expose the `Web3HttpProvider` object on the window object.

```js
// in node.js
var http = require('http');
var Web3HttpProvider = require('web3-providers-http');

var options = {
keepAlive: true,
timeout: 20000, // milliseconds,
headers: [{name: 'Access-Control-Allow-Origin', value: '*'},{...}]
headers: [{name: 'Access-Control-Allow-Origin', value: '*'},{...}],
withCredentials: false,
agent: {http: http.Agent(...), baseUrl: ''}
};
var http = new Web3HttpProvider('http://localhost:8545', options);

var provider = new Web3HttpProvider('http://localhost:8545', options);
```

## Types
Expand Down
32 changes: 20 additions & 12 deletions packages/web3-providers-http/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,21 @@ var https = require('https');
var HttpProvider = function HttpProvider(host, options) {
options = options || {};

var keepAlive = (options.keepAlive === true || options.keepAlive !== false) ? true : false;
this.host = host || 'http://localhost:8545';
if (this.host.substring(0,5) === "https") {
this.httpsAgent = new https.Agent({ keepAlive: keepAlive });
} else {
this.httpAgent = new http.Agent({ keepAlive: keepAlive });
}

this.withCredentials = options.withCredentials || false;
this.timeout = options.timeout || 0;
this.headers = options.headers;
this.agent = options.agent;
this.connected = false;

var keepAlive = (options.keepAlive === true || options.keepAlive !== false) ? true : false;
this.host = host || 'http://localhost:8545';
if (!this.agent) {
if (this.host.substring(0,5) === "https") {
this.httpsAgent = new https.Agent({ keepAlive: keepAlive });
} else {
this.httpAgent = new http.Agent({ keepAlive: keepAlive });
}
}
};

HttpProvider.prototype._prepareRequest = function(){
Expand All @@ -56,10 +59,15 @@ HttpProvider.prototype._prepareRequest = function(){
request = new XMLHttpRequest();
} else {
request = new XHR2();
request.nodejsSet({
httpsAgent:this.httpsAgent,
httpAgent:this.httpAgent
});
var agents = {httpsAgent: this.httpsAgent, httpAgent: this.httpAgent, baseUrl: this.baseUrl};

if (this.agent) {
agents.httpsAgent = this.agent.https;
agents.httpAgent = this.agent.http;
agents.baseUrl = this.agent.baseUrl;
}

request.nodejsSet(agents);
}

request.open('POST', this.host, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* @date 2018
*/

import * as http from 'http';
import * as https from 'https';
import { HttpProvider } from 'web3-providers';
import { JsonRpcResponse } from 'web3-core-helpers';

Expand All @@ -31,7 +33,12 @@ const httpProvider = new HttpProvider('http://localhost:8545', {
value: '*'
}
],
withCredentials: false
withCredentials: false,
agent: {
baseUrl: 'base',
http: new http.Agent({}),
https: new https.Agent({})
}
});

// $ExpectType void
Expand Down
7 changes: 5 additions & 2 deletions test/helpers/FakeXHR2.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ var FakeXHR2 = function () {
this.readyState = 4;
this.onreadystatechange = null;
this.async = true;
this.agents = {};
this.headers = {
'Content-Type': 'text/plain'
};
};

FakeXHR2.prototype.nodejsSet = function (agents) {
this.agents = agents;
};

FakeXHR2.prototype.open = function (method, host, async) {
assert.equal(method, 'POST');
assert.notEqual(host, null);
Expand All @@ -33,6 +38,4 @@ FakeXHR2.prototype.send = function (payload) {
}
};

FakeXHR2.prototype.nodejsSet = Function.prototype;

module.exports = {XMLHttpRequest: FakeXHR2};
51 changes: 49 additions & 2 deletions test/httpprovider.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var chai = require('chai');
var assert = chai.assert;
var http = require('http');
var https = require('https');
var SandboxedModule = require('sandboxed-module');

SandboxedModule.registerBuiltInSourceTransformer('istanbul');
Expand All @@ -13,13 +15,58 @@ var HttpProvider = SandboxedModule.require('../packages/web3-providers-http', {

describe('web3-providers-http', function () {
describe('prepareRequest', function () {
let provider;
let result;
let options;
let agent;

it('should set request header', function () {
var provider = new HttpProvider('http://localhost:8545', {headers: [{name: 'Access-Control-Allow-Origin', value: '*'}]});
var result = provider._prepareRequest();
provider = new HttpProvider('http://localhost:8545', {headers: [{name: 'Access-Control-Allow-Origin', value: '*'}]});
result = provider._prepareRequest();

assert.equal(typeof result, 'object');
assert.equal(result.headers['Access-Control-Allow-Origin'], '*');
});

it('should use the passed custom http agent', function () {
agent = new http.Agent();
options = {agent: {http: agent}};
provider = new HttpProvider('http://localhost:8545', options);
result = provider._prepareRequest();

assert.equal(typeof result, 'object');
assert.equal(result.agents.httpAgent, agent);
assert.equal(provider.httpAgent, undefined);
assert.equal(provider.httpsAgent, undefined);
assert.equal(provider.agent, options.agent);
});

it('should use the passed custom https agent', function () {
agent = new https.Agent();
options = {agent: {https: agent}};
provider = new HttpProvider('http://localhost:8545', options);
result = provider._prepareRequest();

assert.equal(typeof result, 'object');
assert.equal(result.agents.httpsAgent, agent);
assert.equal(provider.httpAgent, undefined);
assert.equal(provider.httpsAgent, undefined);
assert.equal(provider.agent, options.agent);
});

it('should use the passed baseUrl', function () {
agent = new https.Agent();
options = {agent: {https: agent, baseUrl: 'base'}};
provider = new HttpProvider('http://localhost:8545', options);
result = provider._prepareRequest();

assert.equal(typeof result, 'object');
assert.equal(result.agents.httpsAgent, agent);
assert.equal(result.agents.baseUrl, 'base');
assert.equal(provider.httpAgent, undefined);
assert.equal(provider.httpsAgent, undefined);
assert.equal(provider.agent, options.agent);
});
});

describe('send', function () {
Expand Down