From 56b1b9ea2d8016e156d00b3c9277a00b42b85c95 Mon Sep 17 00:00:00 2001 From: Shiranuit Date: Fri, 20 Oct 2023 11:23:25 +0200 Subject: [PATCH 1/4] fix-mcreate --- jest/api/controller/document/mCreate.test.ts | 159 +++++++++++++++++++ lib/service/storage/elasticsearch.js | 4 +- 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 jest/api/controller/document/mCreate.test.ts diff --git a/jest/api/controller/document/mCreate.test.ts b/jest/api/controller/document/mCreate.test.ts new file mode 100644 index 0000000000..7018cdd866 --- /dev/null +++ b/jest/api/controller/document/mCreate.test.ts @@ -0,0 +1,159 @@ +import { Kuzzle, WebSocket } from 'kuzzle-sdk'; + +const kuzzle = new Kuzzle(new WebSocket('localhost')); +const index = 'nyc-open-data'; +const collection = 'yellow-taxi'; + +beforeAll(async () => { + await kuzzle.connect(); + await kuzzle.index.create(index); + await kuzzle.collection.create(index, collection, { + mappings: { + properties: { + value: { + type: 'keyword' + }, + field: { + properties: { + path: { + type: 'keyword' + } + } + } + } + } + }); +}); + +afterAll(async () => { + await kuzzle.index.delete(index); + await kuzzle.disconnect(); +}); + +describe('mCreate', () => { + afterEach(async () => { + await kuzzle.collection.truncate(index, collection); + }); + + + it('It should create document if not exists', async () => { + const mCreateResult = await kuzzle.document.mCreate(index, collection, [ + { + _id: 'A', + body: { + value: 'A' + } + } + ], { + refresh: 'wait_for' + }); + + expect(mCreateResult.successes.length).toEqual(1); + + const result = await kuzzle.document.mGet(index, collection, ['A']); + + expect(result.successes.length).toEqual(1); + expect(result.successes[0]._source).toMatchObject({ + value: 'A' + }); + }); + + it('It should not replace the document if not exists', async () => { + let mCreateResult = await kuzzle.document.mCreate(index, collection, [ + { + _id: 'A', + body: { + value: 'A' + } + } + ], { + refresh: 'wait_for' + }); + + expect(mCreateResult.successes.length).toEqual(1); + + mCreateResult = await kuzzle.document.mCreate(index, collection, [ + { + _id: 'A', + body: { + value: 'FOO' + } + } + ], { + refresh: 'wait_for' + }); + + expect(mCreateResult.successes.length).toEqual(0); + expect(mCreateResult.errors.length).toEqual(1); + + const result = await kuzzle.document.mGet(index, collection, ['A']); + + expect(result.successes.length).toEqual(1); + expect(result.successes[0]._source).toMatchObject({ + value: 'A' + }); + }); + + + it('It should not replace the document even if the previous document did not exist', async () => { + let mCreateResult = await kuzzle.document.mCreate(index, collection, [ + { + _id: 'A', + body: { + value: 'A' + } + }, + { + _id: 'C', + body: { + value: 'C' + } + } + ], { + refresh: 'wait_for' + }); + + expect(mCreateResult.successes.length).toEqual(2); + + mCreateResult = await kuzzle.document.mCreate(index, collection, [ + { + _id: 'A', + body: { + value: 'FOO' + } + }, + { + _id: 'B', + body: { + value: 'B' + } + }, + { + _id: 'C', + body: { + value: 'FOO' + } + } + ], { + refresh: 'wait_for' + }); + + expect(mCreateResult.successes.length).toEqual(1); + expect(mCreateResult.errors.length).toEqual(2); + + const result = await kuzzle.document.mGet(index, collection, ['A', 'B', 'C']); + + expect(result.successes.length).toEqual(3); + expect(result.successes[0]._source).toMatchObject({ + value: 'A' + }); + expect(result.successes[1]._source).toMatchObject({ + value: 'B' + }); + expect(result.successes[2]._source).toMatchObject({ + value: 'C' + }); + }); + + +}); \ No newline at end of file diff --git a/lib/service/storage/elasticsearch.js b/lib/service/storage/elasticsearch.js index 6dd7bab7c8..dbcf88b0fb 100644 --- a/lib/service/storage/elasticsearch.js +++ b/lib/service/storage/elasticsearch.js @@ -2262,7 +2262,6 @@ class ElasticSearch extends Service { status: 400, }); - idx++; } else { esRequest.body.push({ index: { @@ -2271,9 +2270,10 @@ class ElasticSearch extends Service { }, }); esRequest.body.push(document._source); - + toImport.push(document); } + idx++; } else { esRequest.body.push({ index: { _index: alias } }); esRequest.body.push(document._source); From 6a11d4be60ccc2b0c25403bad11b08cc33388892 Mon Sep 17 00:00:00 2001 From: Shiranuit Date: Fri, 20 Oct 2023 11:34:38 +0200 Subject: [PATCH 2/4] lint --- lib/service/storage/elasticsearch.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/service/storage/elasticsearch.js b/lib/service/storage/elasticsearch.js index dbcf88b0fb..d3a8ca28c0 100644 --- a/lib/service/storage/elasticsearch.js +++ b/lib/service/storage/elasticsearch.js @@ -2261,7 +2261,6 @@ class ElasticSearch extends Service { reason: "document already exists", status: 400, }); - } else { esRequest.body.push({ index: { @@ -2270,7 +2269,7 @@ class ElasticSearch extends Service { }, }); esRequest.body.push(document._source); - + toImport.push(document); } idx++; From 244f43647860599f7483e2bfdad9b825d5f1d6fd Mon Sep 17 00:00:00 2001 From: Florian Maunier Date: Tue, 24 Oct 2023 15:53:58 +0200 Subject: [PATCH 3/4] Fix incorrect HTTP Content-Type headers being accepted (#2490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Théo Dislay <44380410+tdislay@users.noreply.github.com> --- lib/core/network/protocols/httpwsProtocol.js | 35 ++++++++++++-------- test/core/network/protocols/http.test.js | 14 ++++++++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/core/network/protocols/httpwsProtocol.js b/lib/core/network/protocols/httpwsProtocol.js index 3876d41037..cefdd5bf5c 100644 --- a/lib/core/network/protocols/httpwsProtocol.js +++ b/lib/core/network/protocols/httpwsProtocol.js @@ -498,23 +498,30 @@ class HttpWsProtocol extends Protocol { return; } - const contentType = message.headers["content-type"]; + const contentTypeHeader = message.headers["content-type"]; - if ( - contentType && - !this.httpConfig.opts.allowedContentTypes.some((allowed) => - contentType.includes(allowed) - ) - ) { - this.httpSendError( - message, - response, - kerrorHTTP.get("unsupported_content", contentType) - ); - return; + if (contentTypeHeader) { + const contentTypeParamIndex = contentTypeHeader.indexOf(";"); + const contentType = + contentTypeParamIndex !== -1 + ? contentTypeHeader.slice(0, contentTypeParamIndex).trim() + : contentTypeHeader.trim(); + + if ( + !this.httpConfig.opts.allowedContentTypes.some( + (allowed) => contentType === allowed + ) + ) { + this.httpSendError( + message, + response, + kerrorHTTP.get("unsupported_content", contentType) + ); + return; + } } - const encoding = CHARSET_REGEX.exec(contentType); + const encoding = CHARSET_REGEX.exec(contentTypeHeader); if (encoding !== null && encoding[1].toLowerCase() !== "utf-8") { this.httpSendError( diff --git a/test/core/network/protocols/http.test.js b/test/core/network/protocols/http.test.js index 640e0292a5..afcb80675c 100644 --- a/test/core/network/protocols/http.test.js +++ b/test/core/network/protocols/http.test.js @@ -357,6 +357,20 @@ describe("core/network/protocols/http", () => { }); }); + it("should reject requests with supported content types with extraneous characters", () => { + httpWs.server._httpOnMessage("get", "/", "", { + "content-type": "serge application/jsoncheval", + }); + + should(entryPoint.newConnection).not.called(); + should(global.kuzzle.router.http.route).not.called(); + should(httpWs.httpSendError) + .calledOnce() + .calledWithMatch(sinon.match.object, httpWs.server._httpResponse, { + id: "network.http.unsupported_content", + }); + }); + it("should reject requests with unhandled charsets", () => { httpWs.server._httpOnMessage("get", "/", "", { "content-type": "application/json; charset=utf-82", From e6648ddd6cf61f5d36244ca966d2228f0ad9151c Mon Sep 17 00:00:00 2001 From: Florian Maunier Date: Tue, 24 Oct 2023 15:57:59 +0200 Subject: [PATCH 4/4] Release 2.27.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3b38aff1b..c9edad4b59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "kuzzle", - "version": "2.27.0", + "version": "2.27.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kuzzle", - "version": "2.27.0", + "version": "2.27.1", "license": "Apache-2.0", "dependencies": { "@elastic/elasticsearch": "https://github.com/elastic/elasticsearch-js/archive/refs/tags/v7.13.0.tar.gz", diff --git a/package.json b/package.json index 6ad71e0dfe..11a3d2bf84 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "kuzzle", "author": "The Kuzzle Team ", - "version": "2.27.0", + "version": "2.27.1", "description": "Kuzzle is an open-source solution that handles all the data management through a secured API, with a large choice of protocols.", "bin": "bin/start-kuzzle-server", "scripts": {