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
| Algorithm | Content-Encoding | Magic Bytes | Node.js Decompressor |
|---|---|---|---|
| gzip | gzip, x-gzip | 0x1F 0x8B | zlib.createGunzip() |
| deflate | deflate, x-deflate | 0x78 | zlib.createInflate() |
| brotli | br, brotli | (heuristic) | zlib.createBrotliDecompress() |
| zstd | zstd | 0x28 0xB5 0x2F 0xFD | zlib.createZstdDecompress() |
| raw deflate | gzip-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
- The first chunk of data is buffered (needs at least 4 bytes)
- Magic bytes are checked against the declared encoding
- If magic bytes match, a decompressor is created and data is piped through it
- If magic bytes do not match, data passes through unmodified
- 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:
- Sends
Accept-Encoding: gzip, deflate, br(orbr, gzip, deflate, zstddepending on the adapter) - Reads the
Content-Encodingheader from the response - Pipes the response through
CompressionUtil.decompressStream() - 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: gzipbut the data is actually plain text (common with misconfigured reverse proxies) - A CDN strips compression but leaves the
Content-Encodingheader 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.