diff --git a/lib/adapters/http.js b/lib/adapters/http.js index 4965cd4859..dc833ccfdf 100755 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -23,6 +23,11 @@ import EventEmitter from 'events'; const zlibOptions = { flush: zlib.constants.Z_SYNC_FLUSH, finishFlush: zlib.constants.Z_SYNC_FLUSH +}; + +const brotliOptions = { + flush: zlib.constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH } const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress); @@ -417,7 +422,9 @@ export default isHttpAdapterSupported && function httpAdapter(config) { switch (res.headers['content-encoding']) { /*eslint default-case:0*/ case 'gzip': + case 'x-gzip': case 'compress': + case 'x-compress': case 'deflate': // add the unzipper to the body stream processing pipeline streams.push(zlib.createUnzip(zlibOptions)); @@ -427,7 +434,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) { break; case 'br': if (isBrotliSupported) { - streams.push(zlib.createBrotliDecompress(zlibOptions)); + streams.push(zlib.createBrotliDecompress(brotliOptions)); delete res.headers['content-encoding']; } } diff --git a/lib/platform/browser/index.js b/lib/platform/browser/index.js index 4ba2c7dbfa..3de84afd6b 100644 --- a/lib/platform/browser/index.js +++ b/lib/platform/browser/index.js @@ -43,6 +43,7 @@ const isStandardBrowserEnv = (() => { const isStandardBrowserWebWorkerEnv = (() => { return ( typeof WorkerGlobalScope !== 'undefined' && + // eslint-disable-next-line no-undef self instanceof WorkerGlobalScope && typeof self.importScripts === 'function' ); diff --git a/test/unit/adapters/http.js b/test/unit/adapters/http.js index 146cdda790..afa616a940 100644 --- a/test/unit/adapters/http.js +++ b/test/unit/adapters/http.js @@ -34,6 +34,8 @@ function setTimeoutAsync(ms) { 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 brotliCompress = util.promisify(zlib.brotliCompress); function toleranceRange(positive, negative) { const p = (1 + 1 / positive); @@ -432,7 +434,7 @@ describe('supports http with nodejs', function () { }); }); - describe('compression', () => { + describe('compression', async () => { it('should support transparent gunzip', function (done) { var data = { firstName: 'Fred', @@ -455,17 +457,17 @@ describe('supports http with nodejs', function () { }); }); - it('should support gunzip error handling', async () => { - server = await startHTTPServer((req, res) => { - res.setHeader('Content-Type', 'application/json'); - res.setHeader('Content-Encoding', 'gzip'); - res.end('invalid response'); - }); + it('should support gunzip error handling', async () => { + server = await startHTTPServer((req, res) => { + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Content-Encoding', 'gzip'); + res.end('invalid response'); + }); - await assert.rejects(async ()=> { - await axios.get(LOCAL_SERVER_URL); - }) - }); + await assert.rejects(async () => { + await axios.get(LOCAL_SERVER_URL); + }) + }); it('should support disabling automatic decompression of response data', function(done) { var data = 'Test data'; @@ -488,32 +490,76 @@ describe('supports http with nodejs', function () { }); }); - it('should properly handle empty responses without Z_BUF_ERROR throwing', async () => { - this.timeout(10000); + describe('algorithms', ()=> { + const responseBody ='str'; + + for (const [type, zipped] of Object.entries({ + gzip: gzip(responseBody), + compress: gzip(responseBody), + deflate: deflate(responseBody), + br: brotliCompress(responseBody) + })) { + describe(`${type} decompression`, async () => { + it(`should support decompression`, async () => { + server = await startHTTPServer(async (req, res) => { + res.setHeader('Content-Encoding', type); + res.end(await zipped); + }); - server = await startHTTPServer((req, res) => { - res.setHeader('Content-Encoding', 'gzip'); - res.end(); - }); + const {data} = await axios.get(LOCAL_SERVER_URL); - await axios.get(LOCAL_SERVER_URL); - }); + assert.strictEqual(data, responseBody); + }); - it('should not fail if response content-length header is missing', async () => { - this.timeout(10000); + it(`should not fail if response content-length header is missing (${type})`, async () => { + server = await startHTTPServer(async (req, res) => { + res.setHeader('Content-Encoding', type); + res.removeHeader('Content-Length'); + res.end(await zipped); + }); - const str = 'zipped'; - const zipped = await gzip(str); + const {data} = await axios.get(LOCAL_SERVER_URL); - server = await startHTTPServer((req, res) => { - res.setHeader('Content-Encoding', 'gzip'); - res.removeHeader('Content-Length'); - res.end(zipped); - }); + assert.strictEqual(data, responseBody); + }); + + it('should not fail with chunked responses (without Content-Length header)', async () => { + server = await startHTTPServer(async (req, res) => { + res.setHeader('Content-Encoding', type); + res.setHeader('Transfer-Encoding', 'chunked'); + res.removeHeader('Content-Length'); + res.write(await zipped); + res.end(); + }); + + const {data} = await axios.get(LOCAL_SERVER_URL); + + assert.strictEqual(data, responseBody); + }); + + it('should not fail with an empty response without content-length header (Z_BUF_ERROR)', async () => { + server = await startHTTPServer((req, res) => { + res.setHeader('Content-Encoding', type); + res.removeHeader('Content-Length'); + res.end(); + }); + + const {data} = await axios.get(LOCAL_SERVER_URL); - const {data} = await axios.get(LOCAL_SERVER_URL); + assert.strictEqual(data, ''); + }); + + it('should not fail with an empty response with content-length header (Z_BUF_ERROR)', async () => { + server = await startHTTPServer((req, res) => { + res.setHeader('Content-Encoding', type); + res.end(); + }); + + await axios.get(LOCAL_SERVER_URL); + }); + }); + } - assert.strictEqual(data, str); }); });