diff --git a/lib/fetch/index.js b/lib/fetch/index.js index cf91a5d378e..c313202fed5 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -1942,6 +1942,7 @@ async function httpNetworkFetch ( } let codings = [] + let location = '' const headers = new Headers() for (let n = 0; n < headersList.length; n += 2) { @@ -1950,6 +1951,8 @@ async function httpNetworkFetch ( if (key.toLowerCase() === 'content-encoding') { codings = val.split(',').map((x) => x.trim()) + } else if (key.toLowerCase() === 'location') { + location = val } headers.append(key, val) @@ -1960,7 +1963,7 @@ async function httpNetworkFetch ( const decoders = [] // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding - if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status)) { + if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !(request.redirect === 'follow' && location)) { for (const coding of codings) { if (/(x-)?gzip/.test(coding)) { decoders.push(zlib.createGunzip()) @@ -1980,7 +1983,7 @@ async function httpNetworkFetch ( statusText, headersList: headers[kHeadersList], body: decoders.length - ? pipeline(this.body, ...decoders, () => {}) + ? pipeline(this.body, ...decoders, () => { }) : this.body.on('error', () => {}) }) diff --git a/test/fetch/client-fetch.js b/test/fetch/client-fetch.js index 0b3453ee1e0..40698c06855 100644 --- a/test/fetch/client-fetch.js +++ b/test/fetch/client-fetch.js @@ -10,6 +10,7 @@ const { fetch, Response, Request, FormData, File } = require('../..') const { Client, setGlobalDispatcher, Agent } = require('../..') const nodeFetch = require('../../index-fetch') const { once } = require('events') +const { gzipSync } = require('zlib') setGlobalDispatcher(new Agent({ keepAliveTimeout: 1, @@ -440,3 +441,30 @@ test('fetching with Request object - issue #1527', async (t) => { await t.resolves(fetch(request)) t.end() }) + +test('do not decode redirect body', (t) => { + t.plan(3) + + const obj = { asd: true } + const server = createServer((req, res) => { + if (req.url === '/resource') { + t.pass('we redirect') + res.statusCode = 301 + res.setHeader('location', '/resource/') + // Some dumb http servers set the content-encoding gzip + // even if there is no response + res.setHeader('content-encoding', 'gzip') + res.end() + return + } + t.pass('actual response') + res.setHeader('content-encoding', 'gzip') + res.end(gzipSync(JSON.stringify(obj))) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const body = await fetch(`http://localhost:${server.address().port}/resource`) + t.strictSame(JSON.stringify(obj), await body.text()) + }) +})