Custom http agent support (#810)

This commit is contained in:
Tomas Della Vedova
2019-04-10 11:13:22 +02:00
committed by delvedor
parent 11c7475566
commit 48233503f7
5 changed files with 82 additions and 16 deletions

View File

@ -90,8 +90,20 @@ _Default:_ `false`
_Default:_ `null` _Default:_ `null`
|`agent` |`agent`
|`http.AgentOptions` - http agent https://nodejs.org/api/http.html#http_new_agent_options[options]. + a|`http.AgentOptions, function` - http agent https://nodejs.org/api/http.html#http_new_agent_options[options], or a function that returns an actual http agent instance. +
_Default:_ `null` _Default:_ `null`
[source,js]
----
const client = new Client({
node: 'http://localhost:9200',
agent: { agent: 'options' }
})
const client = new Client({
node: 'http://localhost:9200',
agent: () => new CustomAgent()
})
----
|`nodeFilter` |`nodeFilter`
a|`function` - Filters which node not to use for a request. + a|`function` - Filters which node not to use for a request. +

4
index.d.ts vendored
View File

@ -29,7 +29,7 @@ import Transport, {
nodeFilterFn, nodeFilterFn,
nodeSelectorFn nodeSelectorFn
} from './lib/Transport'; } from './lib/Transport';
import Connection, { AgentOptions } from './lib/Connection'; import Connection, { AgentOptions, agentFn } from './lib/Connection';
import ConnectionPool, { ResurrectEvent } from './lib/ConnectionPool'; import ConnectionPool, { ResurrectEvent } from './lib/ConnectionPool';
import Serializer from './lib/Serializer'; import Serializer from './lib/Serializer';
import * as RequestParams from './api/requestParams'; import * as RequestParams from './api/requestParams';
@ -82,7 +82,7 @@ interface ClientOptions {
suggestCompression?: boolean; suggestCompression?: boolean;
compression?: 'gzip'; compression?: 'gzip';
ssl?: SecureContextOptions; ssl?: SecureContextOptions;
agent?: AgentOptions; agent?: AgentOptions | agentFn;
nodeFilter?: nodeFilterFn; nodeFilter?: nodeFilterFn;
nodeSelector?: nodeSelectorFn | string; nodeSelector?: nodeSelectorFn | string;
headers?: anyObject; headers?: anyObject;

4
lib/Connection.d.ts vendored
View File

@ -24,12 +24,14 @@ import { inspect, InspectOptions } from 'util';
import * as http from 'http'; import * as http from 'http';
import { SecureContextOptions } from 'tls'; import { SecureContextOptions } from 'tls';
export declare type agentFn = () => any;
interface ConnectionOptions { interface ConnectionOptions {
url: URL; url: URL;
ssl?: SecureContextOptions; ssl?: SecureContextOptions;
id?: string; id?: string;
headers?: any; headers?: any;
agent?: AgentOptions; agent?: AgentOptions | agentFn;
status?: string; status?: string;
roles?: any; roles?: any;
} }

View File

@ -46,18 +46,20 @@ class Connection {
throw new ConfigurationError(`Invalid protocol: '${this.url.protocol}'`) throw new ConfigurationError(`Invalid protocol: '${this.url.protocol}'`)
} }
// Probably there is a bug in Node Core if (typeof opts.agent === 'function') {
// see https://github.com/nodejs/node/issues/26357 this.agent = opts.agent()
const keepAliveFalse = opts.agent && opts.agent.keepAlive === false } else {
const agentOptions = Object.assign({}, { const keepAliveFalse = opts.agent && opts.agent.keepAlive === false
keepAlive: true, const agentOptions = Object.assign({}, {
keepAliveMsecs: 1000, keepAlive: true,
maxSockets: keepAliveFalse ? Infinity : 256, keepAliveMsecs: 1000,
maxFreeSockets: 256 maxSockets: keepAliveFalse ? Infinity : 256,
}, opts.agent) maxFreeSockets: 256
this.agent = this.url.protocol === 'http:' }, opts.agent)
? new http.Agent(agentOptions) this.agent = this.url.protocol === 'http:'
: new https.Agent(Object.assign({}, agentOptions, this.ssl)) ? new http.Agent(agentOptions)
: new https.Agent(Object.assign({}, agentOptions, this.ssl))
}
this.makeRequest = this.url.protocol === 'http:' this.makeRequest = this.url.protocol === 'http:'
? http.request ? http.request

View File

@ -23,6 +23,7 @@ const { test } = require('tap')
const { inspect } = require('util') const { inspect } = require('util')
const { createGzip, createDeflate } = require('zlib') const { createGzip, createDeflate } = require('zlib')
const { URL } = require('url') const { URL } = require('url')
const { Agent } = require('http')
const intoStream = require('into-stream') const intoStream = require('into-stream')
const { buildServer } = require('../utils') const { buildServer } = require('../utils')
const Connection = require('../../lib/Connection') const Connection = require('../../lib/Connection')
@ -149,6 +150,55 @@ test('Basic (https with ssl agent)', t => {
}) })
}) })
test('Custom http agent', t => {
t.plan(5)
function handler (req, res) {
t.match(req.headers, {
'x-custom-test': 'true',
connection: 'keep-alive'
})
res.end('ok')
}
buildServer(handler, ({ port }, server) => {
const agent = new Agent({
keepAlive: true,
keepAliveMsecs: 1000,
maxSockets: 256,
maxFreeSockets: 256
})
agent.custom = true
const connection = new Connection({
url: new URL(`http://localhost:${port}`),
agent: () => agent
})
t.true(connection.agent.custom)
connection.request({
path: '/hello',
method: 'GET',
headers: {
'X-Custom-Test': true
}
}, (err, res) => {
t.error(err)
t.match(res.headers, {
connection: 'keep-alive'
})
var payload = ''
res.setEncoding('utf8')
res.on('data', chunk => { payload += chunk })
res.on('error', err => t.fail(err))
res.on('end', () => {
t.strictEqual(payload, 'ok')
server.stop()
})
})
})
})
test('Disable keep alive', t => { test('Disable keep alive', t => {
t.plan(3) t.plan(3)