From e864c1db9964981a56075bc1d0b373bbc74fab15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:09:22 +0200 Subject: [PATCH] [Backport 7.x] Add ability to disable the http agent (#1258) Co-authored-by: Tomas Della Vedova --- docs/configuration.asciidoc | 9 ++++++- index.d.ts | 2 +- lib/Connection.js | 9 ++++--- package.json | 4 +-- test/types/client-options.test-d.ts | 36 ++++++++++++++++++++++++++ test/types/kibana.test-d.ts | 5 ---- test/unit/client.test.js | 26 +++++++++++++++++++ test/unit/connection.test.js | 39 ++++++++++++++++++++++++++++- 8 files changed, 117 insertions(+), 13 deletions(-) diff --git a/docs/configuration.asciidoc b/docs/configuration.asciidoc index b532dc418..b9850b6e8 100644 --- a/docs/configuration.asciidoc +++ b/docs/configuration.asciidoc @@ -119,7 +119,8 @@ _Default:_ `null` |`agent` 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. + +or a function that returns an actual http agent instance. If you want to disable the http agent use entirely +(and disable the `keep-alive` feature), set the agent to `false`. + _Default:_ `null` [source,js] ---- @@ -132,6 +133,12 @@ const client = new Client({ node: 'http://localhost:9200', agent: () => new CustomAgent() }) + +const client = new Client({ + node: 'http://localhost:9200', + // Disable agent and keep-alive + agent: false +}) ---- |`nodeFilter` diff --git a/index.d.ts b/index.d.ts index 9cb927f8d..b76003eb2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -83,7 +83,7 @@ interface ClientOptions { suggestCompression?: boolean; compression?: 'gzip'; ssl?: TlsConnectionOptions; - agent?: AgentOptions | agentFn; + agent?: AgentOptions | agentFn | false; nodeFilter?: nodeFilterFn; nodeSelector?: nodeSelectorFn | string; headers?: Record; diff --git a/lib/Connection.js b/lib/Connection.js index 731ccae50..7ab7b43a8 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -38,12 +38,13 @@ class Connection { if (typeof opts.agent === 'function') { this.agent = opts.agent() + } else if (opts.agent === false) { + this.agent = undefined } else { - const keepAliveFalse = opts.agent && opts.agent.keepAlive === false const agentOptions = Object.assign({}, { keepAlive: true, keepAliveMsecs: 1000, - maxSockets: keepAliveFalse ? Infinity : 256, + maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo' }, opts.agent) @@ -146,7 +147,9 @@ class Connection { if (this._openRequests > 0) { setTimeout(() => this.close(callback), 1000) } else { - this.agent.destroy() + if (this.agent !== undefined) { + this.agent.destroy() + } callback() } } diff --git a/package.json b/package.json index 9a994c058..a98a5abc3 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ ], "scripts": { "test": "npm run lint && tap test/{unit,acceptance}/{*,**/*}.test.js && npm run test:types", - "test:node8": "npm run lint && tap test/{unit,acceptance}/*.test.js && npm run test:types", + "test:node8": "npm run lint && tap test/{unit,acceptance}/*.test.js", "test:unit": "tap test/unit/{*,**/*}.test.js", "test:acceptance": "tap test/acceptance/*.test.js", "test:integration": "node test/integration/index.js", @@ -68,7 +68,7 @@ "standard": "^13.0.2", "stoppable": "^1.1.0", "tap": "^14.4.1", - "tsd": "^0.12.1", + "tsd": "^0.13.1", "workq": "^2.1.0", "xmlbuilder2": "^2.1.2" }, diff --git a/test/types/client-options.test-d.ts b/test/types/client-options.test-d.ts index db2394432..9628b26cd 100644 --- a/test/types/client-options.test-d.ts +++ b/test/types/client-options.test-d.ts @@ -51,12 +51,14 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 42 }) ) expectError( + // @ts-expect-error new Client({ node: { url: 'http://localhost:9200', @@ -76,6 +78,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', maxRetries: 'five' @@ -93,6 +96,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', requestTimeout: 'five' @@ -110,6 +114,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', pingTimeout: 'five' @@ -134,6 +139,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', sniffInterval: 'five' @@ -151,6 +157,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', sniffOnStart: 'no' @@ -168,6 +175,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', sniffEndpoint: false @@ -185,6 +193,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', sniffOnConnectionFault: 'yes' @@ -216,6 +225,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', resurrectStrategy: 'custom' @@ -233,6 +243,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', suggestCompression: 'no' @@ -250,6 +261,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', compression: 'deflate' @@ -267,6 +279,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', headers: 'foo=bar' @@ -284,6 +297,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', opaqueIdPrefix: 42 @@ -308,6 +322,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', name: 42 @@ -349,6 +364,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', auth: 'password' @@ -367,6 +383,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ cloud: { id: 42 @@ -389,12 +406,22 @@ expectType( }) ) +expectType( + new Client({ + node: 'http://localhost:9200', + agent: false + }) +) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', agent: { + // @ts-expect-error keepAlive: 'yes', + // @ts-expect-error keepAliveMsecs: true, + // @ts-expect-error maxSockets: 'all', maxFreeSockets: null } @@ -418,7 +445,9 @@ expectError( new Client({ node: 'http://localhost:9200', ssl: { + // @ts-expect-error ca: 42, + // @ts-expect-error rejectUnauthorized: 'yes' } }) @@ -437,6 +466,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', generateRequestId: 'id' @@ -463,6 +493,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', nodeSelector (connections) { @@ -484,6 +515,7 @@ expectType( ) expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', nodeFilter (connection) { @@ -518,6 +550,7 @@ expectError( } expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', Serializer: CustomSerializer @@ -553,6 +586,7 @@ expectError( expectError( new Client({ node: 'http://localhost:9200', + // @ts-expect-error Connection: CustomConnection }) ) @@ -584,6 +618,7 @@ expectError( } expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', ConnectionPool: CustomConnectionPool @@ -617,6 +652,7 @@ expectError( } expectError( + // @ts-expect-error new Client({ node: 'http://localhost:9200', Transport: CustomTransport diff --git a/test/types/kibana.test-d.ts b/test/types/kibana.test-d.ts index bd9aefb05..6bc95f6fe 100644 --- a/test/types/kibana.test-d.ts +++ b/test/types/kibana.test-d.ts @@ -90,15 +90,10 @@ expectError( body: 42 }).then(console.log) ) -/* - * We cannot test yet the absence of a property because tsd is still shipping - * TypeScript v3.7, as soon as it will be 3.9, we'll uncomment the following test. // @ts-expect-error client.async_search.get() -*/ - // callback api is not supported expectError(client.cat.count({ index: 'test' }, {}, (err: any, result: any) => {})) diff --git a/test/unit/client.test.js b/test/unit/client.test.js index 8ab7de040..57630bac0 100644 --- a/test/unit/client.test.js +++ b/test/unit/client.test.js @@ -1093,6 +1093,32 @@ test('Random selector', t => { }) }) +test('Disable keep alive agent', t => { + t.plan(3) + + function handler (req, res) { + t.strictEqual(req.headers.connection, 'close') + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + node: `http://localhost:${port}`, + agent: false + }) + + client.search({ + index: 'test', + q: 'foo:bar' + }, (err, { body }) => { + t.error(err) + t.deepEqual(body, { hello: 'world' }) + server.stop() + }) + }) +}) + test('name property as string', t => { t.plan(1) diff --git a/test/unit/connection.test.js b/test/unit/connection.test.js index 1ccdc41b3..2853942f1 100644 --- a/test/unit/connection.test.js +++ b/test/unit/connection.test.js @@ -198,7 +198,7 @@ test('Disable keep alive', t => { buildServer(handler, ({ port }, server) => { const connection = new Connection({ url: new URL(`http://localhost:${port}`), - agent: { keepAlive: false } + agent: false }) connection.request({ path: '/hello', @@ -499,6 +499,43 @@ test('Should not close a connection if there are open requests', t => { }) }) +test('Should not close a connection if there are open requests (with agent disabled)', t => { + t.plan(4) + + function handler (req, res) { + setTimeout(() => res.end('ok'), 1000) + } + + buildServer(handler, ({ port }, server) => { + const connection = new Connection({ + url: new URL(`http://localhost:${port}`), + agent: false + }) + + setTimeout(() => { + t.strictEqual(connection._openRequests, 1) + connection.close() + }, 500) + + connection.request({ + path: '/hello', + method: 'GET' + }, (err, res) => { + t.error(err) + t.strictEqual(connection._openRequests, 0) + + 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('Url with auth', t => { t.plan(2)