From b2c62ba105b7fb9fe2eb6a4ae1b95c8d5b67d428 Mon Sep 17 00:00:00 2001 From: Ajima Chukwuemeka <32770340+ajimae@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:05:58 +0100 Subject: [PATCH] [Fix][ST-29177] Issues with Special Characters ByteLength in SDK (#835) * fix(ts-client): issues with special characters encoding in sdk - install and use browser friendly buffer module to properly read body bytelength * fix(ts-client): issues with special characters encoding in sdk - install and use browser friendly buffer module to properly read body bytelength * chore(release-changeset): changeset - add release changeset * chore(ts-client): buffer type - add checks for Buffer body type * chore(ts-client): add test - add tests to validate functionality * chore(ts-client): add test - add more tests to validate functionality --- .changeset/purple-melons-share.md | 5 ++ examples/browser/browser.html | 6 +- packages/sdk-client-v3/package.json | 1 + .../sdk-client-v3/src/utils/byteLength.ts | 12 +++- .../tests/utils.test/byteLength.test.ts | 62 +++++++++++++++++++ 5 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 .changeset/purple-melons-share.md create mode 100644 packages/sdk-client-v3/tests/utils.test/byteLength.test.ts diff --git a/.changeset/purple-melons-share.md b/.changeset/purple-melons-share.md new file mode 100644 index 000000000..e9c4caf43 --- /dev/null +++ b/.changeset/purple-melons-share.md @@ -0,0 +1,5 @@ +--- +'@commercetools/ts-client': patch +--- + +Fix issues with counting special characters' length diff --git a/examples/browser/browser.html b/examples/browser/browser.html index 31ba3b218..c7bc95f4e 100644 --- a/examples/browser/browser.html +++ b/examples/browser/browser.html @@ -6,7 +6,7 @@ Document - + @@ -27,7 +27,7 @@ clientSecret: '' } var projectKey = ''; - var { ClientBuilder } = this['@commercetools/sdk-client-v2'] + var { ClientBuilder } = this['@commercetools/ts-client'] var client = new ClientBuilder() .defaultClient(baseUri, credentials, oauthUri, projectKey) .build() @@ -45,4 +45,4 @@ - \ No newline at end of file + diff --git a/packages/sdk-client-v3/package.json b/packages/sdk-client-v3/package.json index 6851194fa..453470aad 100644 --- a/packages/sdk-client-v3/package.json +++ b/packages/sdk-client-v3/package.json @@ -34,6 +34,7 @@ }, "dependencies": { "abort-controller": "3.0.0", + "buffer": "^6.0.3", "node-fetch": "^2.6.1" }, "files": ["dist", "CHANGELOG.md"], diff --git a/packages/sdk-client-v3/src/utils/byteLength.ts b/packages/sdk-client-v3/src/utils/byteLength.ts index ae5d35835..decacbeed 100644 --- a/packages/sdk-client-v3/src/utils/byteLength.ts +++ b/packages/sdk-client-v3/src/utils/byteLength.ts @@ -1,7 +1,13 @@ +var Buffer = require('buffer/').Buffer + export default function byteLength(body: T): string { - if (typeof body === 'string') return body.length.toString() - if (body && typeof body === 'object') + if (body && (typeof body === 'string' || body instanceof Uint8Array)) { + return Buffer.byteLength(body).toString() + } + + if (body && typeof body === 'object') { return new TextEncoder().encode(JSON.stringify(body)).length.toString() - if (body instanceof Uint8Array) return body.length.toString() + } + return '0' } diff --git a/packages/sdk-client-v3/tests/utils.test/byteLength.test.ts b/packages/sdk-client-v3/tests/utils.test/byteLength.test.ts new file mode 100644 index 000000000..2c4710a98 --- /dev/null +++ b/packages/sdk-client-v3/tests/utils.test/byteLength.test.ts @@ -0,0 +1,62 @@ +var Buffer = require('buffer/').Buffer +import { byteLength } from '../../src/utils' + +describe('byteLength test', () => { + test('should properly decode a normal character string.', () => { + const str = 'this is a regular/normal characters string' + expect(byteLength(str)).toEqual(str.length.toString()) + }) + + test('should properly decode a special character string.', () => { + const str = 'äëöü' + expect(byteLength(str)).toEqual('8') + expect(str.length.toString()).toEqual('4') + + expect(byteLength(str)).not.toEqual(str.length.toString()) + expect(Number(byteLength(str)) - str.length).not.toEqual(0) + expect(byteLength(str)).toEqual('8') + }) + + test('should show the difference between `String.length` and `Buffer.byteLength`', () => { + const str = 'äëöü' + expect(byteLength(str)).toEqual('8') + expect(str.length.toString()).toEqual('4') + }) + + test('should show there is no difference between `new TextEncoder().encode`', () => { + const str = 'äëöü' + expect(byteLength(str)).toEqual('8') + expect(new TextEncoder().encode(str).length.toString()).toEqual('8') + + const str2 = JSON.stringify({ n: 'äëöü' }) + expect(byteLength(str2)).toEqual('16') + expect(new TextEncoder().encode(str2).length.toString()).toEqual('16') + }) + + test('should return an accurate result of byte length of a string', () => { + const str = 'the string length is 23' + expect(byteLength(str)).toEqual('23') + }) + + test('should return an accurate result of byte length of a Buffer', () => { + const buffer = Buffer.from('the string length is 23') + expect(byteLength(buffer)).toEqual('23') + }) + + test('should return an accurate result of byte length of an object', () => { + const object = { 'byte-length': 18 } + expect(byteLength(object)).toEqual('18') + }) + + test('should return `0` is body is null', () => { + expect(byteLength(null)).toEqual('0') + }) + + test('should return `0` is body is undefined', () => { + expect(byteLength(undefined)).toEqual(`0`) + }) + test('should return `0` is body is not provided', () => { + // @ts-ignore + expect(byteLength()).toEqual('0') + }) +})