From c2bc014abc8818ad93dd69a0e8cc9d36d0dccb9c Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Fri, 15 May 2020 16:30:47 +0200 Subject: [PATCH] Upgrade `decompress-response` to `6.0.0` --- package.json | 1 + source/core/index.ts | 5 +- source/core/utils/decompress-response.ts | 99 ------------------------ 3 files changed, 5 insertions(+), 100 deletions(-) delete mode 100644 source/core/utils/decompress-response.ts diff --git a/package.json b/package.json index cdafc9be2..d5aa09534 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", "get-stream": "^5.1.0", "http2-wrapper": "^1.0.0-beta.4.5", "lowercase-keys": "^2.0.0", diff --git a/source/core/index.ts b/source/core/index.ts index b35a70c9f..6969be6ba 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -10,6 +10,7 @@ import https = require('https'); import timer, {ClientRequestWithTimings, Timings, IncomingMessageWithTimings} from '@szmarczak/http-timer'; import CacheableLookup from 'cacheable-lookup'; import CacheableRequest = require('cacheable-request'); +import decompressResponse = require('decompress-response'); // @ts-ignore Missing types import http2wrapper = require('http2-wrapper'); import lowercaseKeys = require('lowercase-keys'); @@ -23,7 +24,6 @@ import timedOut, {Delays, TimeoutError as TimedOutTimeoutError} from './utils/ti import urlToOptions from './utils/url-to-options'; import optionsToUrl, {URLOptions} from './utils/options-to-url'; import WeakableMap from './utils/weakable-map'; -import decompressResponse from './utils/decompress-response'; type HttpRequestFunction = typeof httpRequest; type Error = NodeJS.ErrnoException; @@ -1234,6 +1234,9 @@ export default class Request extends Duplex implements RequestEvents { const typedResponse = response as unknown as IncomingMessage & {req: ClientRequest}; const {req} = typedResponse; + // TODO: Fix `cacheable-response` + (typedResponse as any)._readableState.autoDestroy = false; + if (req) { req.emit('cacheableResponse', typedResponse); } diff --git a/source/core/utils/decompress-response.ts b/source/core/utils/decompress-response.ts deleted file mode 100644 index 347d3c458..000000000 --- a/source/core/utils/decompress-response.ts +++ /dev/null @@ -1,99 +0,0 @@ -'use strict'; -import {IncomingMessage} from 'http'; -import {Transform, PassThrough} from 'stream'; -import zlib = require('zlib'); - -const knownProperties = [ - 'aborted', - 'complete', - 'headers', - 'httpVersion', - 'httpVersionMinor', - 'httpVersionMajor', - 'method', - 'rawHeaders', - 'rawTrailers', - 'setTimeout', - 'socket', - 'statusCode', - 'statusMessage', - 'trailers', - 'url' -]; - -// TODO: Switch back to the `decompress-response` package when it's fixed -const decompressResponse = (response: IncomingMessage): IncomingMessage => { - const contentEncoding = (response.headers['content-encoding'] ?? '').toLowerCase(); - - if (!['gzip', 'deflate', 'br'].includes(contentEncoding)) { - return response; - } - - // TODO: Remove this when targeting Node.js 12. - const isBrotli = contentEncoding === 'br'; - if (isBrotli && typeof zlib.createBrotliDecompress !== 'function') { - response.destroy(new Error('Brotli is not supported on Node.js < 12')); - return response; - } - - let isEmpty = true; - - const checker = new Transform({ - transform(data, _encoding, callback) { - isEmpty = false; - - callback(null, data); - }, - - flush(callback) { - callback(); - } - }); - - const stream = new PassThrough({ - autoDestroy: false, - destroy(error, callback) { - response.destroy(); - - callback(error); - } - }); - - const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip(); - - decompressStream.once('error', (error: Error) => { - if (isEmpty) { - stream.end(); - return; - } - - stream.destroy(error); - }); - - response.pipe(checker).pipe(decompressStream).pipe(stream); - - response.once('error', error => { - stream.destroy(error); - }); - - const properties: {[key: string]: any} = {}; - - for (const property of knownProperties) { - properties[property] = { - get() { - return (response as any)[property]; - }, - set(value: unknown) { - (response as any)[property] = value; - }, - enumerable: true, - configurable: false - }; - } - - Object.defineProperties(stream, properties); - - return stream as unknown as IncomingMessage; -}; - -export default decompressResponse;