From 4fa6c121c0211ec2696fb5e68e77e23bcc812dba Mon Sep 17 00:00:00 2001 From: Josh Mock Date: Tue, 31 Oct 2023 11:06:01 -0500 Subject: [PATCH 1/3] Add elastic-api-version header to all requests --- src/client.ts | 5 +++-- test/unit/client.test.ts | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 0c2df14..060532f 100644 --- a/src/client.ts +++ b/src/client.ts @@ -52,7 +52,7 @@ if (clientVersion.includes('-')) { // clean prerelease clientVersion = clientVersion.slice(0, clientVersion.indexOf('-')) + 'p' } -const clientVersionNoMeta = clientVersion.split('+')[0] +const [clientVersionNoMeta, apiVersion] = clientVersion.split('+') let transportVersion: string = require('@elastic/transport/package.json').version // eslint-disable-line /* istanbul ignore next */ if (transportVersion.includes('-')) { @@ -162,7 +162,8 @@ export default class Client extends API { caFingerprint: null, agent: null, headers: { - 'user-agent': `elasticsearch-js/${clientVersion} Node.js ${nodeVersion}; Transport ${transportVersion}; (${os.platform()} ${os.release()} ${os.arch()})` + 'user-agent': `elasticsearch-js/${clientVersion} Node.js ${nodeVersion}; Transport ${transportVersion}; (${os.platform()} ${os.release()} ${os.arch()})`, + 'elastic-api-version': `${apiVersion.slice(0, 4)}-${apiVersion.slice(4, 6)}-${apiVersion.slice(6, 8)}` }, generateRequestId: null, name: 'elasticsearch-js', diff --git a/test/unit/client.test.ts b/test/unit/client.test.ts index 019ac01..ad92764 100644 --- a/test/unit/client.test.ts +++ b/test/unit/client.test.ts @@ -404,6 +404,27 @@ test('Meta header disabled', async t => { await client.transport.request({ method: 'GET', path: '/' }) }) +test('elastic-api-version header exists on all requests', async t => { + t.plan(1) + + const Connection = connection.buildMockConnection({ + onRequest (opts) { + t.equal(opts.headers?.['elastic-api-version'], '2023-10-31') + return { + statusCode: 200, + body: { hello: 'world' } + } + } + }) + + const client = new Client({ + node: 'http://localhost:9200', + Connection, + }) + + await client.transport.request({ method: 'GET', path: '/' }) +}) + test('caFingerprint', t => { const client = new Client({ node: 'https://localhost:9200', From 43c7f92157d2a4a5d2ab16407bb9a6e6cfbdcad2 Mon Sep 17 00:00:00 2001 From: Josh Mock Date: Tue, 31 Oct 2023 11:22:23 -0500 Subject: [PATCH 2/3] Use standard MIME types for content-type and accept headers --- src/client.ts | 7 +----- test/integration/test-runner.js | 15 ------------- test/unit/helpers/bulk.test.ts | 38 ++++++++++++++++----------------- 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/client.ts b/src/client.ts index 060532f..63bb93f 100644 --- a/src/client.ts +++ b/src/client.ts @@ -241,12 +241,7 @@ export default class Client extends API { context: options.context, productCheck: 'Elasticsearch', maxResponseSize: options.maxResponseSize, - maxCompressedResponseSize: options.maxCompressedResponseSize, - vendoredHeaders: { - jsonContentType: 'application/vnd.elasticsearch+json; compatible-with=8', - ndjsonContentType: 'application/vnd.elasticsearch+x-ndjson; compatible-with=8', - accept: 'application/vnd.elasticsearch+json; compatible-with=8,text/plain' - } + maxCompressedResponseSize: options.maxCompressedResponseSize }) this.helpers = new Helpers({ diff --git a/test/integration/test-runner.js b/test/integration/test-runner.js index cbbbad9..7118d3f 100644 --- a/test/integration/test-runner.js +++ b/test/integration/test-runner.js @@ -288,21 +288,6 @@ function build (opts = {}) { process.exit(1) } - if (action.headers) { - switch (action.headers['Content-Type'] || action.headers['content-type']) { - case 'application/json': - delete action.headers['Content-Type'] - delete action.headers['content-type'] - action.headers['Content-Type'] = `application/vnd.elasticsearch+json; compatible-with=${packageJson.version.split('.')[0]}` - break - case 'application/x-ndjson': - delete action.headers['Content-Type'] - delete action.headers['content-type'] - action.headers['Content-Type'] = `application/vnd.elasticsearch+x-ndjson; compatible-with=${packageJson.version.split('.')[0]}` - break - } - } - const options = { ignore: cmd.params.ignore, headers: action.headers, meta: true } if (!Array.isArray(options.ignore)) options.ignore = [options.ignore] if (cmd.params.ignore) delete cmd.params.ignore diff --git a/test/unit/helpers/bulk.test.ts b/test/unit/helpers/bulk.test.ts index 5ec9eca..fa8e3b5 100644 --- a/test/unit/helpers/bulk.test.ts +++ b/test/unit/helpers/bulk.test.ts @@ -56,7 +56,7 @@ test('bulk index', t => { onRequest (params) { t.equal(params.path, '/_bulk') t.match(params.headers, { - 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8', + 'content-type': 'application/x-ndjson', 'x-elastic-client-meta': `esv=${clientVersionNoMeta},js=${nodeVersion},t=${transportVersion},hc=${nodeVersion},h=bp` }) // @ts-expect-error @@ -103,7 +103,7 @@ test('bulk index', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) t.notMatch(params.headers, { 'x-elastic-client-meta': `esv=${clientVersionNoMeta},js=${nodeVersion},t=${transportVersion},hc=${nodeVersion},h=bp` }) @@ -150,7 +150,7 @@ test('bulk index', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error t.equal(params.body.split('\n').filter(Boolean).length, 6) return { body: { errors: false, items: new Array(3).fill({}) } } @@ -192,7 +192,7 @@ test('bulk index', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { index: { _index: 'test', _id: count } }) @@ -238,7 +238,7 @@ test('bulk index', t => { t.test('Should perform a bulk request (retry)', async t => { async function handler (req: http.IncomingMessage, res: http.ServerResponse) { t.equal(req.url, '/_bulk') - t.match(req.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(req.headers, { 'content-type': 'application/x-ndjson' }) let body = '' req.setEncoding('utf8') @@ -359,7 +359,7 @@ test('bulk index', t => { t.test('Should perform a bulk request (failure)', async t => { async function handler (req: http.IncomingMessage, res: http.ServerResponse) { t.equal(req.url, '/_bulk') - t.match(req.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(req.headers, { 'content-type': 'application/x-ndjson' }) let body = '' req.setEncoding('utf8') @@ -503,7 +503,7 @@ test('bulk index', t => { t.test('Should abort a bulk request', async t => { async function handler (req: http.IncomingMessage, res: http.ServerResponse) { t.equal(req.url, '/_bulk') - t.match(req.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(req.headers, { 'content-type': 'application/x-ndjson' }) let body = '' req.setEncoding('utf8') @@ -606,7 +606,7 @@ test('bulk index', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { index: { _index: 'test', _id: count } }) @@ -660,7 +660,7 @@ test('bulk index', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { index: { _index: 'test' } }) @@ -718,7 +718,7 @@ test('bulk create', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { create: { _index: 'test', _id: count } }) @@ -769,7 +769,7 @@ test('bulk update', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { update: { _index: 'test', _id: count } }) @@ -819,7 +819,7 @@ test('bulk update', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { update: { _index: 'test', _id: count } }) @@ -867,7 +867,7 @@ test('bulk update', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { update: { _index: 'test', _id: count } }) @@ -922,7 +922,7 @@ test('bulk delete', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error t.same(JSON.parse(params.body), { delete: { _index: 'test', _id: count++ } }) return { body: { errors: false, items: [{}] } } @@ -966,7 +966,7 @@ test('bulk delete', t => { t.test('Should perform a bulk request (failure)', async t => { async function handler (req: http.IncomingMessage, res: http.ServerResponse) { t.equal(req.url, '/_bulk') - t.match(req.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(req.headers, { 'content-type': 'application/x-ndjson' }) let body = '' req.setEncoding('utf8') @@ -1115,7 +1115,7 @@ test('transport options', t => { if (params.path === '/_bulk') { t.match(params.headers, { - 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8', + 'content-type': 'application/x-ndjson', foo: 'bar' }) return { body: { errors: false, items: [{}] } } @@ -1231,7 +1231,7 @@ test('Flush interval', t => { const MockConnection = connection.buildMockConnection({ onRequest (params) { t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { index: { _index: 'test' } }) @@ -1285,7 +1285,7 @@ test('Flush interval', t => { onRequest (params) { t.ok(count < 2) t.equal(params.path, '/_bulk') - t.match(params.headers, { 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8' }) + t.match(params.headers, { 'content-type': 'application/x-ndjson' }) // @ts-expect-error const [action, payload] = params.body.split('\n') t.same(JSON.parse(action), { index: { _index: 'test' } }) @@ -1345,7 +1345,7 @@ test('Flush interval', t => { onRequest (params) { t.equal(params.path, '/_bulk') t.match(params.headers, { - 'content-type': 'application/vnd.elasticsearch+x-ndjson; compatible-with=8', + 'content-type': 'application/x-ndjson', 'x-elastic-client-meta': `esv=${clientVersionNoMeta},js=${nodeVersion},t=${transportVersion},hc=${nodeVersion},h=bp` }) // @ts-expect-error From 68805661be1dde8cc7b28da4d342ec0f4332e342 Mon Sep 17 00:00:00 2001 From: Josh Mock Date: Tue, 31 Oct 2023 11:27:09 -0500 Subject: [PATCH 3/3] Github workflows don't support YAML anchors --- .github/workflows/tests.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ea0005a..86a843b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,7 +2,7 @@ name: Unit tests on: push: - paths-ignore: &ignore + paths-ignore: - '**/*.md' - '**/*.asciidoc' - '**/*.txt' @@ -12,7 +12,15 @@ on: - 'scripts/**' - 'catalog-info.yaml' pull_request: - paths-ignore: *ignore + paths-ignore: + - '**/*.md' + - '**/*.asciidoc' + - '**/*.txt' + - 'docs/**' + - '.ci/**' + - '.buildkite/**' + - 'scripts/**' + - 'catalog-info.yaml' jobs: test: