diff --git a/.changeset/dirty-moles-exercise.md b/.changeset/dirty-moles-exercise.md new file mode 100644 index 0000000..dd3e50e --- /dev/null +++ b/.changeset/dirty-moles-exercise.md @@ -0,0 +1,5 @@ +--- +"@remix-run/web-fetch": patch +--- + +fix: Remove content-encoding header from already decompressed responses. This eases the use of fetch in senarios where you wish to use it as a sort of makeshift proxy. diff --git a/packages/fetch/src/fetch.js b/packages/fetch/src/fetch.js index 6a76542..026318c 100644 --- a/packages/fetch/src/fetch.js +++ b/packages/fetch/src/fetch.js @@ -277,6 +277,7 @@ async function fetch(url, options_ = {}) { // For gzip if (codings === 'gzip' || codings === 'x-gzip') { + responseOptions.headers.delete("Content-Encoding"); body = pump(body, zlib.createGunzip(zlibOptions), reject); response = new Response(fromAsyncIterable(body), responseOptions); resolve(response); @@ -285,6 +286,7 @@ async function fetch(url, options_ = {}) { // For deflate if (codings === 'deflate' || codings === 'x-deflate') { + responseOptions.headers.delete("Content-Encoding"); // Handle the infamous raw deflate response from old servers // a hack for old IIS and Apache servers const raw = pump(response_, new PassThrough(), reject); @@ -304,6 +306,7 @@ async function fetch(url, options_ = {}) { // For br if (codings === 'br') { + responseOptions.headers.delete("Content-Encoding"); body = pump(body, zlib.createBrotliDecompress(), reject); response = new Response(fromAsyncIterable(body), responseOptions); resolve(response); diff --git a/packages/fetch/test/main.js b/packages/fetch/test/main.js index 9388bce..df360a9 100644 --- a/packages/fetch/test/main.js +++ b/packages/fetch/test/main.js @@ -818,6 +818,7 @@ describe("node-fetch", () => { const url = `${base}gzip`; return fetch(url).then((res) => { expect(res.headers.get("content-type")).to.equal("text/plain"); + expect(res.headers.get("content-encoding")).to.be.null; return res.text().then((result) => { expect(result).to.be.a("string"); expect(result).to.equal("hello world"); @@ -836,10 +837,9 @@ describe("node-fetch", () => { }); }); - it("should make capitalised Content-Encoding lowercase", () => { + it("should decompress capitalised Content-Encoding", () => { const url = `${base}gzip-capital`; return fetch(url).then((res) => { - expect(res.headers.get("content-encoding")).to.equal("gzip"); return res.text().then((result) => { expect(result).to.be.a("string"); expect(result).to.equal("hello world"); @@ -851,6 +851,7 @@ describe("node-fetch", () => { const url = `${base}deflate`; return fetch(url).then((res) => { expect(res.headers.get("content-type")).to.equal("text/plain"); + expect(res.headers.get("content-encoding")).to.be.null; return res.text().then((result) => { expect(result).to.be.a("string"); expect(result).to.equal("hello world"); @@ -877,6 +878,7 @@ describe("node-fetch", () => { const url = `${base}brotli`; return fetch(url).then((res) => { expect(res.headers.get("content-type")).to.equal("text/plain"); + expect(res.headers.get("content-encoding")).to.be.null; return res.text().then((result) => { expect(result).to.be.a("string"); expect(result).to.equal("hello world"); @@ -906,6 +908,7 @@ describe("node-fetch", () => { const url = `${base}sdch`; return fetch(url).then((res) => { expect(res.headers.get("content-type")).to.equal("text/plain"); + expect(res.headers.get("content-encoding")).to.equal("sdch"); return res.text().then((result) => { expect(result).to.be.a("string"); expect(result).to.equal("fake sdch string"); @@ -957,6 +960,7 @@ describe("node-fetch", () => { }; return fetch(url, options).then((res) => { expect(res.headers.get("content-type")).to.equal("text/plain"); + expect(res.headers.get("content-encoding")).to.equal("gzip"); return res.text().then((result) => { expect(result).to.be.a("string"); expect(result).to.not.equal("hello world");