diff --git a/lib/adapters/http.js b/lib/adapters/http.js index 10c24ce727..4965cd4859 100755 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -20,6 +20,11 @@ import AxiosHeaders from '../core/AxiosHeaders.js'; import AxiosTransformStream from '../helpers/AxiosTransformStream.js'; import EventEmitter from 'events'; +const zlibOptions = { + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH +} + const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress); const {http: httpFollow, https: httpsFollow} = followRedirects; @@ -262,7 +267,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) { } } - const contentLength = +headers.getContentLength(); + const contentLength = utils.toFiniteNumber(headers.getContentLength()); if (utils.isArray(maxRate)) { maxUploadRate = maxRate[0]; @@ -277,7 +282,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) { } data = stream.pipeline([data, new AxiosTransformStream({ - length: utils.toFiniteNumber(contentLength), + length: contentLength, maxRate: utils.toFiniteNumber(maxUploadRate) })], utils.noop); @@ -320,7 +325,10 @@ export default isHttpAdapterSupported && function httpAdapter(config) { return reject(customErr); } - headers.set('Accept-Encoding', 'gzip, deflate, br', false); + headers.set( + 'Accept-Encoding', + 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''), false + ); const options = { path, @@ -392,17 +400,17 @@ export default isHttpAdapterSupported && function httpAdapter(config) { streams.push(transformStream); } - // uncompress the response body transparently if required + // decompress the response body transparently if required let responseStream = res; // return the last request in case of redirects const lastRequest = res.req || req; // if decompress disabled we should not decompress - if (config.decompress !== false) { + if (config.decompress !== false && res.headers['content-encoding']) { // if no content, but headers still say that it is encoded, // remove the header not confuse downstream operations - if ((!responseLength || res.statusCode === 204) && res.headers['content-encoding']) { + if (method === 'HEAD' || res.statusCode === 204) { delete res.headers['content-encoding']; } @@ -412,14 +420,14 @@ export default isHttpAdapterSupported && function httpAdapter(config) { case 'compress': case 'deflate': // add the unzipper to the body stream processing pipeline - streams.push(zlib.createUnzip()); + streams.push(zlib.createUnzip(zlibOptions)); // remove the content-encoding in order to not confuse downstream operations delete res.headers['content-encoding']; break; case 'br': if (isBrotliSupported) { - streams.push(zlib.createBrotliDecompress()); + streams.push(zlib.createBrotliDecompress(zlibOptions)); delete res.headers['content-encoding']; } } diff --git a/test/unit/adapters/http.js b/test/unit/adapters/http.js index 92a11a75e0..146cdda790 100644 --- a/test/unit/adapters/http.js +++ b/test/unit/adapters/http.js @@ -33,6 +33,7 @@ function setTimeoutAsync(ms) { const pipelineAsync = util.promisify(stream.pipeline); const finishedAsync = util.promisify(stream.finished); +const gzip = util.promisify(zlib.gzip); function toleranceRange(positive, negative) { const p = (1 + 1 / positive); @@ -497,6 +498,23 @@ describe('supports http with nodejs', function () { await axios.get(LOCAL_SERVER_URL); }); + + it('should not fail if response content-length header is missing', async () => { + this.timeout(10000); + + const str = 'zipped'; + const zipped = await gzip(str); + + server = await startHTTPServer((req, res) => { + res.setHeader('Content-Encoding', 'gzip'); + res.removeHeader('Content-Length'); + res.end(zipped); + }); + + const {data} = await axios.get(LOCAL_SERVER_URL); + + assert.strictEqual(data, str); + }); }); it('should support UTF8', function (done) { @@ -1411,7 +1429,6 @@ describe('supports http with nodejs', function () { it('should omit a user-agent if one is explicitly disclaimed', function (done) { server = http.createServer(function (req, res) { - console.log(req.headers); assert.equal("user-agent" in req.headers, false); assert.equal("User-Agent" in req.headers, false); res.end();