From 8b82f36bf6d4ac0163563ce3a10f0a395bd87627 Mon Sep 17 00:00:00 2001 From: Rich Ellis Date: Fri, 17 Dec 2021 19:09:59 +0000 Subject: [PATCH] fix: avoid Buffer re-encode during compression (#184) If the data is already a Buffer then just compress it, don't convert it to a string and back to a Buffer again before compressing it. A test with Buffer input is added. The input is chosen carefully to ensure that if it was assumed to be UTF-8 encoded it would not be the same when decompressed and added an additional assertion for the decompressed data to match the original. --- lib/request-wrapper.ts | 2 ++ test/unit/request-wrapper.test.js | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/request-wrapper.ts b/lib/request-wrapper.ts index f918747b9..0faf53463 100644 --- a/lib/request-wrapper.ts +++ b/lib/request-wrapper.ts @@ -444,6 +444,8 @@ export class RequestWrapper { if (isStream(data)) { const streamData = await streamToPromise(data); reqBuffer = Buffer.isBuffer(streamData) ? streamData : Buffer.from(streamData); + } else if (Buffer.isBuffer(data)) { + reqBuffer = data; } else if (data.toString && data.toString() !== '[object Object]' && !Array.isArray(data)) { // this handles pretty much any primitive that isnt a JSON object or array reqBuffer = Buffer.from(data.toString()); diff --git a/test/unit/request-wrapper.test.js b/test/unit/request-wrapper.test.js index 5c74aefe5..a07261de5 100644 --- a/test/unit/request-wrapper.test.js +++ b/test/unit/request-wrapper.test.js @@ -908,6 +908,19 @@ describe('gzipRequestBody', () => { expect(headers['Content-Encoding']).toBe('gzip'); }); + it('should compress buffer data into a buffer', async () => { + // Use an invalid UTF-8 overlong encoding as example binary data + const originalData = Buffer.from('f08282ac', 'hex'); + const headers = {}; + + const data = await requestWrapperInstance.gzipRequestBody(originalData, headers); + expect(data).toBeInstanceOf(Buffer); + expect(gzipSpy).toHaveBeenCalled(); + expect(headers['Content-Encoding']).toBe('gzip'); + // If UTF-8 has been assumed the data will not match + expect(zlib.gunzipSync(data)).toEqual(originalData); + }); + it('should log an error and return data unaltered if data cant be stringified', async () => { let data = { key: 'value' }; data.circle = data;