59 lines
1.3 KiB
JavaScript
59 lines
1.3 KiB
JavaScript
|
'use strict';
|
||
|
const {Transform, PassThrough} = require('stream');
|
||
|
const zlib = require('zlib');
|
||
|
const mimicResponse = require('mimic-response');
|
||
|
|
||
|
module.exports = response => {
|
||
|
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 finalStream = new PassThrough({
|
||
|
autoDestroy: false,
|
||
|
destroy(error, callback) {
|
||
|
response.destroy();
|
||
|
|
||
|
callback(error);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
|
||
|
|
||
|
decompressStream.once('error', error => {
|
||
|
if (isEmpty && !response.readable) {
|
||
|
finalStream.end();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
finalStream.destroy(error);
|
||
|
});
|
||
|
|
||
|
mimicResponse(response, finalStream);
|
||
|
response.pipe(checker).pipe(decompressStream).pipe(finalStream);
|
||
|
|
||
|
return finalStream;
|
||
|
};
|