index.js 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. 'use strict';
  2. const {Transform, PassThrough} = require('stream');
  3. const zlib = require('zlib');
  4. const mimicResponse = require('mimic-response');
  5. module.exports = response => {
  6. const contentEncoding = (response.headers['content-encoding'] || '').toLowerCase();
  7. if (!['gzip', 'deflate', 'br'].includes(contentEncoding)) {
  8. return response;
  9. }
  10. // TODO: Remove this when targeting Node.js 12.
  11. const isBrotli = contentEncoding === 'br';
  12. if (isBrotli && typeof zlib.createBrotliDecompress !== 'function') {
  13. response.destroy(new Error('Brotli is not supported on Node.js < 12'));
  14. return response;
  15. }
  16. let isEmpty = true;
  17. const checker = new Transform({
  18. transform(data, _encoding, callback) {
  19. isEmpty = false;
  20. callback(null, data);
  21. },
  22. flush(callback) {
  23. callback();
  24. }
  25. });
  26. const finalStream = new PassThrough({
  27. autoDestroy: false,
  28. destroy(error, callback) {
  29. response.destroy();
  30. callback(error);
  31. }
  32. });
  33. const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
  34. decompressStream.once('error', error => {
  35. if (isEmpty && !response.readable) {
  36. finalStream.end();
  37. return;
  38. }
  39. finalStream.destroy(error);
  40. });
  41. mimicResponse(response, finalStream);
  42. response.pipe(checker).pipe(decompressStream).pipe(finalStream);
  43. return finalStream;
  44. };