From 5efd55772a703e227978b70a831ad074c4413ba3 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Sat, 27 Jan 2024 08:28:20 +0100 Subject: [PATCH 1/3] fix: support deflate raw responses --- lib/fetch/index.js | 9 +++++---- lib/fetch/util.js | 38 +++++++++++++++++++++++++++++++++++++- test/node-fetch/main.js | 2 +- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/lib/fetch/index.js b/lib/fetch/index.js index 75939e18599..bd51fc45dc4 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -43,7 +43,8 @@ const { urlHasHttpsScheme, clampAndCoursenConnectionTimingInfo, simpleRangeHeaderValue, - buildContentRange + buildContentRange, + createInflate } = require('./util') const { kState, kHeaders, kGuard, kRealm } = require('./symbols') const assert = require('assert') @@ -1096,7 +1097,7 @@ function fetchFinale (fetchParams, response) { // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm // set to processResponseEndOfBody. const transformStream = new TransformStream({ - start () {}, + start () { }, transform (chunk, controller) { controller.enqueue(chunk) }, @@ -2186,7 +2187,7 @@ async function httpNetworkFetch ( finishFlush: zlib.constants.Z_SYNC_FLUSH })) } else if (coding === 'deflate') { - decoders.push(zlib.createInflate()) + decoders.push(createInflate()) } else if (coding === 'br') { decoders.push(zlib.createBrotliDecompress()) } else { @@ -2202,7 +2203,7 @@ async function httpNetworkFetch ( headersList, body: decoders.length ? pipeline(this.body, ...decoders, () => { }) - : this.body.on('error', () => {}) + : this.body.on('error', () => { }) }) return true diff --git a/lib/fetch/util.js b/lib/fetch/util.js index 03f0e004037..9a3fd22c6a4 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -1,5 +1,7 @@ 'use strict' +const { Transform } = require('node:stream') +const zlib = require('node:zlib') const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require('./constants') const { getGlobalOrigin } = require('./global') const { performance } = require('perf_hooks') @@ -1174,6 +1176,39 @@ function buildContentRange (rangeStart, rangeEnd, fullLength) { return contentRange } +// A Stream, which pipes the response to zlib.createInflate() or +// zlib.createInflateRaw() depending on the first byte of the Buffer. +// If the lower byte of the first byte is 0x08, then the stream is +// interpreted as a zlib stream, otherwise it's interpreted as a +// raw deflate stream. +class InflateStream extends Transform { + _transform (chunk, encoding, callback) { + if (!this._inflateStream) { + this._inflateStream = (chunk[0] & 0x0F) === 0x08 + ? zlib.createInflate() + : zlib.createInflateRaw() + + this._inflateStream.on('data', this.push.bind(this)) + this._inflateStream.on('end', callback) + this._inflateStream.on('error', callback) + } + + this._inflateStream.write(chunk, encoding, callback) + } + + _final (callback) { + if (this._inflateStream) { + this._inflateStream.end() + this._inflateStream = null + } + callback() + } +} + +function createInflate () { + return new InflateStream() +} + module.exports = { isAborted, isCancelled, @@ -1221,5 +1256,6 @@ module.exports = { normalizeMethodRecord, simpleRangeHeaderValue, buildContentRange, - parseMetadata + parseMetadata, + createInflate } diff --git a/test/node-fetch/main.js b/test/node-fetch/main.js index d702a2743fc..6c96680e901 100644 --- a/test/node-fetch/main.js +++ b/test/node-fetch/main.js @@ -659,7 +659,7 @@ describe('node-fetch', () => { }) }) - xit('should decompress deflate raw response from old apache server', () => { + it('should decompress deflate raw response from old apache server', () => { const url = `${base}deflate-raw` return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain') From b05230c516d3d6e0e07a830ec59fa77901a10476 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Sat, 27 Jan 2024 08:52:54 +0100 Subject: [PATCH 2/3] fix: support deflate raw responses --- lib/fetch/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fetch/util.js b/lib/fetch/util.js index 9a3fd22c6a4..53e1d40a456 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -1189,8 +1189,8 @@ class InflateStream extends Transform { : zlib.createInflateRaw() this._inflateStream.on('data', this.push.bind(this)) - this._inflateStream.on('end', callback) - this._inflateStream.on('error', callback) + this._inflateStream.on('end', () => this.push(null)) + this._inflateStream.on('error', (err) => this.destroy(err)) } this._inflateStream.write(chunk, encoding, callback) From 09b68f05e1e05e5a3aff854f9d8c57dfca5efa17 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 27 Jan 2024 12:06:33 +0100 Subject: [PATCH 3/3] Update lib/fetch/util.js --- lib/fetch/util.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/fetch/util.js b/lib/fetch/util.js index 53e1d40a456..7e917f019d0 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -1184,6 +1184,10 @@ function buildContentRange (rangeStart, rangeEnd, fullLength) { class InflateStream extends Transform { _transform (chunk, encoding, callback) { if (!this._inflateStream) { + if (chunk.length === 0) { + callback() + return + } this._inflateStream = (chunk[0] & 0x0F) === 0x08 ? zlib.createInflate() : zlib.createInflateRaw()