🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

@fastify/compress

Package Overview
Dependencies
Maintainers
16
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fastify/compress - npm Package Compare versions

Comparing version
8.0.3
to
8.1.0
+8
.claude/settings.local.json
{
"permissions": {
"allow": [
"mcp__ripgrep__search"
],
"deny": []
}
}
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Development Commands
### Testing
- `npm run test` - Run both unit and TypeScript tests
- `npm run test:unit` - Run unit tests with Node.js test runner
- `npm run test:coverage` - Run tests with coverage reporting
- `npm run lint` - Run ESLint for code style checking
- `npm run lint:fix` - Auto-fix linting issues
### Running Single Tests
Use Node.js test runner with file path:
```bash
node --test test/global-compress.test.js
```
## Architecture Overview
This is a Fastify plugin (`@fastify/compress`) that provides compression and decompression capabilities for HTTP requests and responses.
### Core Components
**Main Plugin (`index.js`)**: 574-line plugin implementation using Fastify's hook system:
- `onSend` hook for response compression
- `preParsing` hook for request decompression
- `onRoute` hook for route-level configuration
**Utilities (`lib/utils.js`)**: Core compression detection and stream handling:
- `isZstd()` / `isGzip()` / `isDeflate()` - Magic byte detection (RFC 8878/1952/1950)
- `isStream()` - Stream type checking
- `intoAsyncIterator()` - Payload conversion utilities
**TypeScript Support (`types/index.d.ts`)**: Full type definitions with Fastify module augmentation
### Compression System
**Supported Encodings**: zstd (Node.js 22.15+/23.8+), brotli (`br`), gzip, deflate, identity
**Priority Order**: zstd > br > gzip > deflate > * (defaults to gzip) > identity
**Threshold-based**: Default 1024 bytes minimum for compression
**Content-Type Aware**: Uses `mime-db` for compressible content detection
### Configuration Levels
1. **Global**: Applied to all routes via plugin options
2. **Route-level**: Override global settings in route config
3. **Runtime**: Manual compression via `reply.compress()`
### Key Dependencies
- `@fastify/accept-negotiator` - Content encoding negotiation
- `fastify-plugin` - Plugin registration
- `mime-db` - MIME type database
- `minipass`, `pump`, `pumpify` - Stream processing
### Testing Structure
Uses Node.js built-in test runner with describe/test pattern. Test files are organized by functionality:
- `global-compress.test.js` / `global-decompress.test.js` - Global functionality
- `routes-compress.test.js` / `routes-decompress.test.js` - Route-level functionality
- `utils.test.js` - Utility functions
- `regression/` - Regression tests
### Code Style
Uses `neostandard` (ESLint-based) with TypeScript support. Configuration in `eslint.config.js`.
+17
-0

@@ -148,2 +148,5 @@ 'use strict'

}
if (typeof ((opts.zlib || zlib).createZstdCompress || zlib.createZstdCompress) === 'function') {
params.compressStream.zstd = () => ((opts.zlib || zlib).createZstdCompress || zlib.createZstdCompress)(params.zlibOptions)
}
params.uncompressStream = {

@@ -156,4 +159,12 @@ // Currently params.uncompressStream.br() is never called as we do not have any way to autodetect brotli compression in `fastify-compress`

}
if (typeof ((opts.zlib || zlib).createZstdDecompress || zlib.createZstdDecompress) === 'function') {
// Currently params.uncompressStream.zstd() is never called as we do not have any way to autodetect zstd compression in `fastify-compress`
// Zstd documentation reference: [RFC 8878](https://www.rfc-editor.org/rfc/rfc8878)
params.uncompressStream.zstd = /* c8 ignore next */ () => ((opts.zlib || zlib).createZstdDecompress || zlib.createZstdDecompress)(params.zlibOptions)
}
const supportedEncodings = ['br', 'gzip', 'deflate', 'identity']
if (typeof zlib.createZstdCompress === 'function') {
supportedEncodings.unshift('zstd')
}

@@ -189,4 +200,10 @@ params.encodings = Array.isArray(opts.encodings)

}
if (typeof (customZlib.createZstdDecompress || zlib.createZstdDecompress) === 'function') {
params.decompressStream.zstd = customZlib.createZstdDecompress || zlib.createZstdDecompress
}
const supportedEncodings = ['br', 'gzip', 'deflate', 'identity']
if (typeof zlib.createZstdCompress === 'function') {
supportedEncodings.unshift('zstd')
}

@@ -193,0 +210,0 @@ params.encodings = Array.isArray(opts.requestEncodings)

+15
-1
'use strict'
// https://datatracker.ietf.org/doc/html/rfc8878#section-3.1.1
function isZstd (buffer) {
return (
typeof buffer === 'object' &&
buffer !== null &&
buffer.length > 3 &&
// Zstd magic number: 0xFD2FB528 (little-endian)
buffer[0] === 0x28 &&
buffer[1] === 0xb5 &&
buffer[2] === 0x2f &&
buffer[3] === 0xfd
)
}
// https://datatracker.ietf.org/doc/html/rfc1950#section-2

@@ -79,2 +93,2 @@ function isDeflate (buffer) {

module.exports = { isGzip, isDeflate, isStream, intoAsyncIterator }
module.exports = { isZstd, isGzip, isDeflate, isStream, intoAsyncIterator }
+3
-1
MIT License
Copyright (c) 2017 Fastify
Copyright (c) 2017-present The Fastify team
The Fastify team members are listed at https://github.com/fastify/fastify#team.
Permission is hereby granted, free of charge, to any person obtaining a copy

@@ -6,0 +8,0 @@ of this software and associated documentation files (the "Software"), to deal

{
"name": "@fastify/compress",
"version": "8.0.3",
"version": "8.1.0",
"description": "Fastify compression utils",

@@ -27,4 +27,4 @@ "main": "index.js",

"neostandard": "^0.12.0",
"tsd": "^0.31.0",
"typescript": "~5.7.2"
"tsd": "^0.32.0",
"typescript": "~5.8.3"
},

@@ -45,3 +45,4 @@ "scripts": {

"gzip",
"brotli"
"brotli",
"zstd"
],

@@ -48,0 +49,0 @@ "author": "Tomas Della Vedova - @delvedor (http://delved.org)",

@@ -8,3 +8,3 @@ # @fastify/compress

Adds compression utils to [the Fastify `reply` object](https://fastify.dev/docs/latest/Reference/Reply/#reply) and a hook to decompress requests payloads.
Supports `gzip`, `deflate`, and `brotli`.
Supports `gzip`, `deflate`, `brotli`, and `zstd` (Node.js 22.15+/23.8+).

@@ -41,7 +41,8 @@ > ℹ️ Note: In large-scale scenarios, use a proxy like Nginx to handle response compression.

1. `br`
2. `gzip`
3. `deflate`
4. `*` (no preference — `@fastify/compress` will use `gzip`)
5. `identity` (no compression)
1. `zstd` (Node.js 22.15+/23.8+)
2. `br`
3. `gzip`
4. `deflate`
5. `*` (no preference — `@fastify/compress` will use `gzip`)
6. `identity` (no compression)

@@ -180,2 +181,9 @@ If an unsupported encoding is received or the `'accept-encoding'` header is missing, the payload will not be compressed.

)
// Example with zstd support (Node.js 22.15+/23.8+)
await fastify.register(
import('@fastify/compress'),
// Prefer zstd, fallback to brotli, then gzip
{ encodings: ['zstd', 'br', 'gzip'] }
)
```

@@ -220,5 +228,6 @@

1. `br`
2. `gzip`
3. `deflate`
1. `zstd` (Node.js 22.15+/23.8+)
2. `br`
3. `gzip`
4. `deflate`

@@ -275,2 +284,9 @@ If an unsupported encoding or invalid payload is received, the plugin throws an error.

)
// Example with zstd support for request decompression (Node.js 22.15+/23.8+)
await fastify.register(
import('@fastify/compress'),
// Support zstd, brotli and gzip for request decompression
{ requestEncodings: ['zstd', 'br', 'gzip'] }
)
```

@@ -277,0 +293,0 @@

@@ -45,2 +45,29 @@ 'use strict'

test('using zstd algorithm when `Content-Encoding` request header value is set to `zstd`', async (t) => {
if (typeof zlib.createZstdCompress !== 'function') {
t.skip('zstd not supported in this Node.js version')
return
}
t.plan(2)
const fastify = Fastify()
await fastify.register(compressPlugin)
fastify.post('/', (request, reply) => {
reply.send(request.body.name)
})
const response = await fastify.inject({
url: '/',
method: 'POST',
headers: {
'content-type': 'application/json',
'content-encoding': 'zstd'
},
payload: createPayload(zlib.createZstdCompress)
})
t.assert.equal(response.statusCode, 200)
t.assert.equal(response.body, '@fastify/compress')
})
test('using deflate algorithm when `Content-Encoding` request header value is set to `deflate`', async (t) => {

@@ -47,0 +74,0 @@ t.plan(2)

@@ -7,3 +7,3 @@ 'use strict'

const { test } = require('node:test')
const { isStream, isDeflate, isGzip, intoAsyncIterator } = require('../lib/utils')
const { isStream, isZstd, isDeflate, isGzip, intoAsyncIterator } = require('../lib/utils')

@@ -52,2 +52,19 @@ test('isStream() utility should be able to detect Streams', async (t) => {

test('isZstd() utility should be able to detect zstd compressed Buffer', async (t) => {
t.plan(10)
const equal = t.assert.equal
equal(isZstd(Buffer.alloc(0)), false)
equal(isZstd(Buffer.alloc(1)), false)
equal(isZstd(Buffer.alloc(2)), false)
equal(isZstd(Buffer.alloc(3)), false)
equal(isZstd(Buffer.from([0x28, 0xb5, 0x2f])), false)
equal(isZstd(Buffer.from([0x28, 0xb5, 0x2f, 0xfd])), true)
equal(isZstd({}), false)
equal(isZstd(null), false)
equal(isZstd(undefined), false)
equal(isZstd(''), false)
})
test('isGzip() utility should be able to detect gzip compressed Buffer', async (t) => {

@@ -54,0 +71,0 @@ t.plan(10)

@@ -60,3 +60,3 @@ import {

type EncodingToken = 'br' | 'deflate' | 'gzip' | 'identity'
type EncodingToken = 'zstd' | 'br' | 'deflate' | 'gzip' | 'identity'

@@ -63,0 +63,0 @@ type CompressibleContentTypeFunction = (contentType: string) => boolean

@@ -28,4 +28,10 @@ import fastify, { FastifyInstance } from 'fastify'

const withZstdOptions: FastifyCompressOptions = {
encodings: ['zstd', 'br', 'gzip', 'deflate', 'identity'],
requestEncodings: ['zstd', 'br', 'gzip', 'deflate', 'identity']
}
const app: FastifyInstance = fastify()
app.register(fastifyCompress, withGlobalOptions)
app.register(fastifyCompress, withZstdOptions)

@@ -115,2 +121,11 @@ app.register(fastifyCompress, {

// Test that invalid encoding values trigger TypeScript errors
expectError(fastify().register(fastifyCompress, {
encodings: ['invalid-encoding']
}))
expectError(fastify().register(fastifyCompress, {
requestEncodings: ['another-invalid-encoding']
}))
// Instantiation of an app that should trigger a typescript error

@@ -117,0 +132,0 @@ const appThatTriggerAnError = fastify()

Sorry, the diff of this file is too big to display