diff --git a/lib/adapters/http.js b/lib/adapters/http.js index dc833ccfdf..2d9c5e12a6 100755 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -19,6 +19,7 @@ import stream from 'stream'; import AxiosHeaders from '../core/AxiosHeaders.js'; import AxiosTransformStream from '../helpers/AxiosTransformStream.js'; import EventEmitter from 'events'; +import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js'; const zlibOptions = { flush: zlib.constants.Z_SYNC_FLUSH, @@ -425,7 +426,15 @@ export default isHttpAdapterSupported && function httpAdapter(config) { case 'x-gzip': case 'compress': case 'x-compress': + // add the unzipper to the body stream processing pipeline + streams.push(zlib.createUnzip(zlibOptions)); + + // remove the content-encoding in order to not confuse downstream operations + delete res.headers['content-encoding']; + break; case 'deflate': + streams.push(new ZlibHeaderTransformStream()); + // add the unzipper to the body stream processing pipeline streams.push(zlib.createUnzip(zlibOptions)); diff --git a/lib/helpers/ZlibHeaderTransformStream.js b/lib/helpers/ZlibHeaderTransformStream.js new file mode 100644 index 0000000000..d1791f0b8e --- /dev/null +++ b/lib/helpers/ZlibHeaderTransformStream.js @@ -0,0 +1,28 @@ +"use strict"; + +import stream from "stream"; + +class ZlibHeaderTransformStream extends stream.Transform { + __transform(chunk, encoding, callback) { + this.push(chunk); + callback(); + } + + _transform(chunk, encoding, callback) { + if (chunk.length !== 0) { + this._transform = this.__transform; + + // Add Default Compression headers if no zlib headers are present + if (chunk[0] !== 120) { // Hex: 78 + const header = Buffer.alloc(2); + header[0] = 120; // Hex: 78 + header[1] = 156; // Hex: 9C + this.push(header, encoding); + } + } + + this.__transform(chunk, encoding, callback); + } +} + +export default ZlibHeaderTransformStream; diff --git a/test/unit/adapters/http.js b/test/unit/adapters/http.js index afa616a940..9d44c48af1 100644 --- a/test/unit/adapters/http.js +++ b/test/unit/adapters/http.js @@ -35,6 +35,7 @@ const pipelineAsync = util.promisify(stream.pipeline); const finishedAsync = util.promisify(stream.finished); const gzip = util.promisify(zlib.gzip); const deflate = util.promisify(zlib.deflate); +const deflateRaw = util.promisify(zlib.deflateRaw); const brotliCompress = util.promisify(zlib.brotliCompress); function toleranceRange(positive, negative) { @@ -493,13 +494,16 @@ describe('supports http with nodejs', function () { describe('algorithms', ()=> { const responseBody ='str'; - for (const [type, zipped] of Object.entries({ + for (const [typeName, zipped] of Object.entries({ gzip: gzip(responseBody), compress: gzip(responseBody), deflate: deflate(responseBody), + 'deflate-raw': deflateRaw(responseBody), br: brotliCompress(responseBody) })) { - describe(`${type} decompression`, async () => { + const type = typeName.split('-')[0]; + + describe(`${typeName} decompression`, async () => { it(`should support decompression`, async () => { server = await startHTTPServer(async (req, res) => { res.setHeader('Content-Encoding', type);