Utilities

Compression

The CompressionUtil class provides smart stream decompression that handles servers which incorrectly report their Content-Encoding. Instead of blindly trusting the header, it inspects magic bytes in the first few bytes of the response to verify the data is actually compressed before applying decompression.

import { CompressionUtil } from 'rezo';

Supported Algorithms

AlgorithmContent-EncodingMagic BytesNode.js Decompressor
gzipgzip, x-gzip0x1F 0x8Bzlib.createGunzip()
deflatedeflate, x-deflate0x78zlib.createInflate()
brotlibr, brotli(heuristic)zlib.createBrotliDecompress()
zstdzstd0x28 0xB5 0x2F 0xFDzlib.createZstdDecompress()
raw deflategzip-raw(any)zlib.createInflate({ windowBits: 15 })

CompressionUtil.decompressStream()

The primary API. Takes an IncomingMessage response and returns either a decompression transform stream or the original response if no decompression is needed:

// Decompression is automatic - just enable it
const { data } = await rezo.get('https://api.example.com/data', {
  decompress: true // enabled by default
});

When contentEncoding is undefined or empty, the original response is returned unchanged.

Configuration-Aware Decompression

Pass a Rezo config object to control decompression behavior:

const stream = CompressionUtil.decompressStream(response, encoding, {
  decompress: false,  // Skip decompression entirely
});

const stream = CompressionUtil.decompressStream(response, encoding, {
  compression: {
    enabled: false,   // Disable compression handling
  },
});

const stream = CompressionUtil.decompressStream(response, encoding, {
  compression: {
    algorithms: ['gzip', 'br'],  // Only decompress these algorithms
  },
});

SmartDecompressStream

Rezo includes a smart decompression layer that performs magic-byte detection before decompression. This solves a common problem: servers that send Content-Encoding: gzip but return uncompressed data.

How It Works

  1. The first chunk of data is buffered (needs at least 4 bytes)
  2. Magic bytes are checked against the declared encoding
  3. If magic bytes match, a decompressor is created and data is piped through it
  4. If magic bytes do not match, data passes through unmodified
  5. Subsequent chunks are routed to either the decompressor or passthrough

Magic Byte Detection

gzip: First two bytes must be 0x1F 0x8B.

deflate: First byte must be 0x78 (zlib header). Valid second bytes include 0x01, 0x5E, 0x9C, 0xDA.

zstd: First four bytes must be 0x28 0xB5 0x2F 0xFD (Zstandard magic number).

brotli: Brotli has no magic bytes, so heuristic detection is used:

  • If the data starts with common text characters ({, [, ", <, digits), it is probably uncompressed
  • If the data starts with a UTF-8 BOM (0xEF 0xBB 0xBF), it is uncompressed
  • If 80%+ of the first 16 bytes are printable ASCII, it is uncompressed
  • Otherwise, assume brotli compression

Error Recovery

If decompression fails mid-stream (corrupt data), SmartDecompressStream emits an error via destroy(). For small responses that fit entirely in the initial buffer, a failed decompression falls back to returning the raw data.

Utility Methods

CompressionUtil.isSupported(encoding)

Check if an encoding is supported:

CompressionUtil.isSupported('gzip');    // true
CompressionUtil.isSupported('br');      // true
CompressionUtil.isSupported('zstd');    // true
CompressionUtil.isSupported('snappy');  // false

CompressionUtil.getSupportedAlgorithms()

List all supported encoding names:

CompressionUtil.getSupportedAlgorithms();
// ['gzip', 'x-gzip', 'deflate', 'x-deflate', 'gzip-raw', 'br', 'brotli', 'zstd']

CompressionUtil.shouldDecompress(encoding, config?)

Check if decompression should be performed based on config options:

CompressionUtil.shouldDecompress('gzip');
// true (default)

CompressionUtil.shouldDecompress('gzip', { decompress: false });
// false

CompressionUtil.shouldDecompress('zstd', {
  compression: { algorithms: ['gzip', 'br'] },
});
// false (zstd not in allowed algorithms)

How Rezo Uses Compression

The HTTP adapter automatically:

  1. Sends Accept-Encoding: gzip, deflate, br (or br, gzip, deflate, zstd depending on the adapter)
  2. Reads the Content-Encoding header from the response
  3. Pipes the response through CompressionUtil.decompressStream()
  4. Returns the decompressed data in response.data

You can disable this per-request:

import rezo from 'rezo';

// Disable decompression
const response = await rezo.get('https://api.example.com/data', {
  decompress: false,
});

// Limit algorithms
const response = await rezo.get('https://api.example.com/data', {
  compression: {
    algorithms: ['gzip'],  // Only decompress gzip
  },
});

Why Smart Detection Matters

In practice, many servers and CDNs misconfigure compression:

  • A server sends Content-Encoding: gzip but the data is actually plain text (common with misconfigured reverse proxies)
  • A CDN strips compression but leaves the Content-Encoding header intact
  • An API gateway double-compresses data

Without smart detection, these scenarios cause cryptic errors like Z_DATA_ERROR or produce garbage output. SmartDecompressStream handles all of these gracefully by verifying before decompressing.