Skip to content

Commit dd2cea4

Browse files
authored
Handle zero-length OK deflate responses (master) (#965)
* Handle zero-length OK deflate responses * Also handle pump callback in the deflate branch * Update the use of pump everywhere and link to the original PR * Address lints
1 parent 92dee09 commit dd2cea4

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

src/index.js

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,11 @@ export default async function fetch(url, options_) {
235235
});
236236
}
237237

238-
let body = pump(response_, new PassThrough(), reject);
238+
let body = pump(response_, new PassThrough(), error => {
239+
if (error) {
240+
reject(error);
241+
}
242+
});
239243
// see https://github.com/nodejs/node/pull/29376
240244
/* c8 ignore next 3 */
241245
if (process.version < 'v12.10') {
@@ -281,7 +285,11 @@ export default async function fetch(url, options_) {
281285

282286
// For gzip
283287
if (codings === 'gzip' || codings === 'x-gzip') {
284-
body = pump(body, zlib.createGunzip(zlibOptions), reject);
288+
body = pump(body, zlib.createGunzip(zlibOptions), error => {
289+
if (error) {
290+
reject(error);
291+
}
292+
});
285293
response = new Response(body, responseOptions);
286294
resolve(response);
287295
return;
@@ -291,20 +299,48 @@ export default async function fetch(url, options_) {
291299
if (codings === 'deflate' || codings === 'x-deflate') {
292300
// Handle the infamous raw deflate response from old servers
293301
// a hack for old IIS and Apache servers
294-
const raw = pump(response_, new PassThrough(), reject);
302+
const raw = pump(response_, new PassThrough(), error => {
303+
if (error) {
304+
reject(error);
305+
}
306+
});
295307
raw.once('data', chunk => {
296308
// See http://stackoverflow.com/questions/37519828
297-
body = (chunk[0] & 0x0F) === 0x08 ? pump(body, zlib.createInflate(), reject) : pump(body, zlib.createInflateRaw(), reject);
309+
if ((chunk[0] & 0x0F) === 0x08) {
310+
body = pump(body, zlib.createInflate(), error => {
311+
if (error) {
312+
reject(error);
313+
}
314+
});
315+
} else {
316+
body = pump(body, zlib.createInflateRaw(), error => {
317+
if (error) {
318+
reject(error);
319+
}
320+
});
321+
}
298322

299323
response = new Response(body, responseOptions);
300324
resolve(response);
301325
});
326+
raw.once('end', () => {
327+
// Some old IIS servers return zero-length OK deflate responses, so
328+
// 'data' is never emitted. See https://github.com/node-fetch/node-fetch/pull/903
329+
if (!response) {
330+
response = new Response(body, responseOptions);
331+
resolve(response);
332+
}
333+
});
302334
return;
303335
}
304336

305337
// For br
306338
if (codings === 'br') {
307-
body = pump(body, zlib.createBrotliDecompress(), reject);
339+
body = pump(body, zlib.createBrotliDecompress(), error => {
340+
if (error) {
341+
reject(error);
342+
}
343+
});
308344
response = new Response(body, responseOptions);
309345
resolve(response);
310346
return;

test/main.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,17 @@ describe('node-fetch', () => {
946946
});
947947
});
948948

949+
it('should handle empty deflate response', () => {
950+
const url = `${base}empty/deflate`;
951+
return fetch(url).then(res => {
952+
expect(res.headers.get('content-type')).to.equal('text/plain');
953+
return res.text().then(result => {
954+
expect(result).to.be.a('string');
955+
expect(result).to.be.empty;
956+
});
957+
});
958+
});
959+
949960
it('should decompress brotli response', function () {
950961
if (typeof zlib.createBrotliDecompress !== 'function') {
951962
this.skip();

test/utils/server.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ export default class TestServer {
179179
});
180180
}
181181

182+
if (p === '/empty/deflate') {
183+
res.statusCode = 200;
184+
res.setHeader('Content-Type', 'text/plain');
185+
res.setHeader('Content-Encoding', 'deflate');
186+
res.end();
187+
}
188+
182189
if (p === '/sdch') {
183190
res.statusCode = 200;
184191
res.setHeader('Content-Type', 'text/plain');

0 commit comments

Comments
 (0)