The request decompression middleware automatically handles compressed request payloads sent by clients. This allows the API to accept requests with compressed bodies, reducing bandwidth usage while maintaining full compatibility with uncompressed requests.
The middleware supports the following Content-Encoding values:
- gzip / x-gzip: The most common compression format, widely supported by browsers and HTTP clients
- deflate: The raw DEFLATE algorithm, sometimes used by legacy clients
- br (Brotli): Modern compression format with better compression ratios, supported by modern browsers
- Detection: The middleware checks the
Content-Encodingheader on incoming requests - Decompression: If a supported encoding is detected, the request body is automatically decompressed using the appropriate Node.js zlib decompression stream
- Cleanup: The
Content-Encodingheader is removed after decompression to prevent downstream handlers from attempting to decompress again - Transparent Processing: The rest of the application sees uncompressed request data and operates normally
Request with Content-Encoding: gzip
↓
DecompressionMiddleware
↓
Detect encoding
↓
Create decompressor stream
↓
Pipe request through decompressor
↓
Remove Content-Encoding header
↓
Uncompressed request → Application
- No External Dependencies: Uses Node.js built-in
zlibmodule - Error Handling: Graceful error handling with appropriate HTTP 400 responses for decompression failures
- Pass-through: Requests without compression or with unsupported encodings are passed through unchanged
- Safe Skip: GET, HEAD, and DELETE requests are skipped (they shouldn't have bodies)
- Case-Insensitive: Encoding values are normalized to lowercase for compatibility
// Using node-fetch or axios with gzip compression
const response = await fetch('https://api.example.com/endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Encoding': 'gzip',
},
body: gzipCompressedBuffer, // Pre-compressed payload
});# Send gzip-compressed data
curl -X POST https://api.example.com/endpoint \
-H "Content-Encoding: gzip" \
-H "Content-Type: application/json" \
--data-binary @compressed_payload.gz
# Send brotli-compressed data
curl -X POST https://api.example.com/endpoint \
-H "Content-Encoding: br" \
-H "Content-Type: application/json" \
--compressedimport gzip
import requests
data = b'{"key": "value"}'
compressed = gzip.compress(data)
response = requests.post(
'https://api.example.com/endpoint',
headers={
'Content-Encoding': 'gzip',
'Content-Type': 'application/json'
},
data=compressed
)The middleware implements comprehensive error handling:
If decompression fails (e.g., corrupted compressed data), the middleware returns:
{
"statusCode": 400,
"message": "Failed to decompress request body with encoding: gzip",
"error": "Bad Request"
}Unsupported encodings are logged and the request passes through unchanged. If the client expects the server to handle an unsupported encoding, the downstream application will handle it appropriately.
- gzip: Typically achieves 40-70% size reduction for JSON payloads
- brotli: Typically achieves 45-75% size reduction for JSON payloads (better than gzip)
- deflate: Similar compression to gzip, usually 40-70% reduction
- Decompression is generally faster than compression and has minimal CPU impact
- Node.js zlib module is highly optimized and uses native bindings
Original payload: 100 KB
Gzip compressed: 30 KB (70% reduction)
Network transfer: 30 KB instead of 100 KB
Decompression time: ~5ms (CPU cost)
Bandwidth saved: 70 KB per request
The middleware includes comprehensive unit tests covering:
- All supported compression formats
- Case-insensitive encoding detection
- Proper header removal
- Error handling and edge cases
- Request method filtering (GET, HEAD, DELETE)
Run tests with:
npm test -- src/common/middleware/decompression.middleware.spec.tsCurrently, the middleware doesn't require any environment variables. It automatically supports all standard compression formats.
Potential configuration options for future versions:
// Example future configuration
export interface DecompressionConfig {
// Maximum decompressed size (default: 10MB)
maxDecompressedSize?: number;
// Compression formats to support
supportedFormats?: ('gzip' | 'deflate' | 'br')[];
// Timeout for decompression
decompressionTimeoutMs?: number;
}The DecompressionMiddleware is positioned:
Request
↓
helmet (security headers)
↓
DecompressionMiddleware ← YOU ARE HERE
↓
express.json()
↓
express.urlencoded()
↓
correlation middleware
↓
session middleware
↓
[Rest of application]
This ordering ensures:
- Security headers are set first
- Decompression happens before body parsing
- Decompressed data is properly parsed as JSON/URL-encoded
- Correlation IDs and sessions work with decompressed requests
Cause: The compressed data is corrupted or not actually gzip-compressed
Solution:
- Verify the data is properly compressed with the specified algorithm
- Check for network transmission issues
- Ensure no intermediate proxies are double-compressing
Cause: The middleware might not have been applied or the encoding header is missing
Solution:
- Verify the middleware is registered in main.ts
- Check that the
Content-Encodingheader is set correctly - Ensure no other middleware is intercepting requests
Cause: Decompression of very large payloads consumes CPU
Solution:
- Consider compression on client-side only for payloads > 1KB
- Monitor decompression times in production
- Scale horizontally if decompression CPU usage is high
- Decompression Bomb Protection: While the middleware doesn't implement explicit limits, consider setting
REQUEST_BODY_LIMITenvironment variable - Denial of Service: Monitor for patterns of excessive decompression requests
- Content-Encoding Attacks: The middleware safely handles invalid/corrupted compression
- Node.js zlib documentation
- HTTP Content-Encoding header (MDN)
- Request Body Size Limits
- Performance Optimization Guide
✅ Gzip decompression
✅ Brotli decompression
✅ Deflate decompression
✅ Content-Encoding header handling
✅ Error handling
✅ Unit tests
✅ Documentation
- Issue: #651 - Implement request decompression handling
- Module:
src/common/middleware/decompression.middleware.ts - Tests:
src/common/middleware/decompression.middleware.spec.ts - Integration:
src/main.ts(lines for middleware registration)