diff --git a/CHANGELOG.md b/CHANGELOG.md index a9abbc7e757..9253f86e379 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/packages/web3-core-helpers/types/index.d.ts b/packages/web3-core-helpers/types/index.d.ts index 337bd76fa2d..b969f5d521c 100644 --- a/packages/web3-core-helpers/types/index.d.ts +++ b/packages/web3-core-helpers/types/index.d.ts @@ -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; @@ -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 { diff --git a/packages/web3-providers-http/README.md b/packages/web3-providers-http/README.md index 5c9a0a52087..5f684a4d1c3 100644 --- a/packages/web3-providers-http/README.md +++ b/packages/web3-providers-http/README.md @@ -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 diff --git a/packages/web3-providers-http/src/index.js b/packages/web3-providers-http/src/index.js index 1aa75032607..ca0cb28fcea 100644 --- a/packages/web3-providers-http/src/index.js +++ b/packages/web3-providers-http/src/index.js @@ -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(){ @@ -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); diff --git a/packages/web3-providers-http/types/tests/web3-provider-http-tests.ts b/packages/web3-providers-http/types/tests/web3-provider-http-tests.ts index 59048f9782c..798a84b7b62 100644 --- a/packages/web3-providers-http/types/tests/web3-provider-http-tests.ts +++ b/packages/web3-providers-http/types/tests/web3-provider-http-tests.ts @@ -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'; @@ -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 diff --git a/test/helpers/FakeXHR2.js b/test/helpers/FakeXHR2.js index 06e512d8711..92e63cf59fc 100644 --- a/test/helpers/FakeXHR2.js +++ b/test/helpers/FakeXHR2.js @@ -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); @@ -33,6 +38,4 @@ FakeXHR2.prototype.send = function (payload) { } }; -FakeXHR2.prototype.nodejsSet = Function.prototype; - module.exports = {XMLHttpRequest: FakeXHR2}; diff --git a/test/httpprovider.js b/test/httpprovider.js index de545bae522..105cb022666 100644 --- a/test/httpprovider.js +++ b/test/httpprovider.js @@ -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'); @@ -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 () {