New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

fastify-compress

Package Overview
Dependencies
Maintainers
8
Versions
38
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 0.11.0 to 1.0.0

3

index.d.ts
import { Plugin } from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'
type EncodingToken = 'br' | 'deflate' | 'gzip' | 'identity'
declare const fastifyCompress: Plugin<

@@ -15,2 +17,3 @@ Server,

inflateIfDeflated?: boolean
encodings?: Array<EncodingToken>
}

@@ -17,0 +20,0 @@ >

57

index.js

@@ -40,8 +40,22 @@ 'use strict'

compressStream.br = opts.brotli.compressStream
supportedEncodings.push('br')
supportedEncodings.unshift('br')
} else if (zlib.createBrotliCompress) {
compressStream.br = zlib.createBrotliCompress
supportedEncodings.push('br')
supportedEncodings.unshift('br')
}
if (opts.encodings && opts.encodings.length < 1) {
next(new Error('The `encodings` option array must have at least 1 item.'))
}
const encodings = Array.isArray(opts.encodings)
? supportedEncodings
.filter(encoding => opts.encodings.includes(encoding))
.sort((a, b) => opts.encodings.indexOf(a) - supportedEncodings.indexOf(b))
: supportedEncodings
if (encodings.length < 1) {
next(new Error('None of the passed `encodings` were supported — compression not possible.'))
}
next()

@@ -60,6 +74,6 @@

(this.request.headers['x-no-compression'] !== undefined) ||
// don't compress if not one of the indiated compressible types
// don't compress if not one of the indicated compressible types
(shouldCompress(this.getHeader('Content-Type') || 'application/json', compressibleTypes) === false) ||
// don't compress on missing or identity `accept-encoding` header
((encoding = getEncodingHeader(supportedEncodings, this.request)) === undefined || encoding === 'identity')
((encoding = getEncodingHeader(encodings, this.request)) == null || encoding === 'identity')

@@ -76,8 +90,2 @@ if (noCompress) {

if (encoding === null) {
closeStream(payload)
this.code(406).send(new Error('Unsupported encoding'))
return
}
if (typeof payload.pipe !== 'function') {

@@ -118,3 +126,3 @@ if (!Buffer.isBuffer(payload) && typeof payload !== 'string') {

// don't compress on missing or identity `accept-encoding` header
((encoding = getEncodingHeader(supportedEncodings, req)) === undefined || encoding === 'identity')
((encoding = getEncodingHeader(encodings, req)) == null || encoding === 'identity')

@@ -131,9 +139,2 @@ if (noCompress) {

if (encoding === null) {
closeStream(payload)
reply.code(406)
next(new Error('Unsupported encoding'))
return
}
if (typeof payload.pipe !== 'function') {

@@ -160,17 +161,13 @@ if (Buffer.byteLength(payload) < threshold) {

function closeStream (payload) {
if (typeof payload.close === 'function') {
payload.close()
} else if (typeof payload.destroy === 'function') {
payload.destroy()
} else if (typeof payload.abort === 'function') {
payload.abort()
function getEncodingHeader (encodings, request) {
let header = request.headers['accept-encoding']
if (header != null) {
header = header.toLowerCase()
.replace('*', 'gzip') // consider the no-preference token as gzip for downstream compat
return encodingNegotiator.negotiate(header, encodings)
} else {
return undefined
}
}
function getEncodingHeader (supportedEncodings, request) {
const header = request.headers['accept-encoding']
return encodingNegotiator.negotiate(header, supportedEncodings)
}
function shouldCompress (type, compressibleTypes) {

@@ -177,0 +174,0 @@ if (compressibleTypes.test(type)) return true

{
"name": "fastify-compress",
"version": "0.11.0",
"version": "1.0.0",
"description": "Fastify compression utils",

@@ -15,7 +15,7 @@ "main": "index.js",

"mime-db": "^1.33.0",
"minipass": "2.3.5",
"minipass": "^2.9.0",
"peek-stream": "^1.1.0",
"pump": "^3.0.0",
"pumpify": "^2.0.0",
"string-to-stream": "^2.0.0",
"string-to-stream": "^3.0.0",
"unzipper": "^0.10.1"

@@ -48,3 +48,3 @@ },

"gzip",
"brodli"
"brotli"
],

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

@@ -7,27 +7,27 @@ # fastify-compress

Adds compression utils to the Fastify `reply` object.
Support `gzip`, `deflate` and `brotli`.
Adds compression utils to [the Fastify `reply` object](https://www.fastify.io/docs/master/Reply/).
Supports `gzip`, `deflate`, and `brotli`.
## Install
```
npm i fastify-compress --save
npm i fastify-compress
```
## Usage
This plugins adds two functionalities to Fastify, a compress utility and a global compression hook.
This plugin adds two functionalities to Fastify: a compress utility and a global compression hook.
Currently the following headers are supported:
- `'deflate'`
- `'gzip'`
- `'br'`
- `'*'`
Currently, the following encoding tokens are supported, using the first acceptable token in this order:
If the `'accept-encoding'` header specifies no preferred encoding with an asterisk `*` the payload will be compressed with `gzip`.
1. `br`
2. `gzip`
3. `deflate`
4. `*` (no preference — `fastify-compress` will use `gzip`)
5. `identity` (no compression)
If an unsupported encoding is received, it will automatically return a `406` error, if the `'accept-encoding'` header is missing, it will not compress the payload.
If the `accept-encoding` header is missing or contains no supported encodings, it will not compress the payload.
It automatically defines if a payload should be compressed or not based on its `Content-Type`, if no content type is present, it will assume is `application/json`.
The plugin automatically decides if a payload should be compressed based on its `content-type`; if no content type is present, it will assume `application/json`.
### Global hook
The global compression hook is enabled by default if you want to disable it, pass the option `{ global: false }`.
The global compression hook is enabled by default. To disable it, pass the option `{ global: false }`:
```javascript

@@ -39,6 +39,6 @@ fastify.register(

```
Remember that thanks to the Fastify encapsulation model, you can set a global compression, but running it only in a subset of routes is you wrap them inside a plugin.
Remember that thanks to the Fastify encapsulation model, you can set a global compression, but run it only in a subset of routes if you wrap them inside a plugin.
### `reply.compress`
This plugin add a `compress` function to `reply` that accepts a stream or a string and compress it based on the `'accept-encoding'` header. If a js object is passed in, will be stringified as json.
This plugin adds a `compress` method to `reply` that accepts a stream or a string, and compresses it based on the `accept-encoding` header. If a JS object is passed in, it will be stringified to JSON.

@@ -64,3 +64,3 @@ ```javascript

### Threshold
You can set a custom threshold below which it will not be made compression, default to `1024`.
The minimum byte size for a response to be compressed. Defaults to `1024`.
```javascript

@@ -73,3 +73,3 @@ fastify.register(

### customTypes
[mime-db](https://github.com/jshttp/mime-db) is used to determine if a `Content-Type` should be compressed. You can compress additional content types via regular expression.
[mime-db](https://github.com/jshttp/mime-db) is used to determine if a `content-type` should be compressed. You can compress additional content types via regular expression.
```javascript

@@ -82,5 +82,5 @@ fastify.register(

### Brotli
Brotli compression is enabled by default if your Node.js(>= v11.7.0) supports it natively.
Brotli compression is enabled by default if your Node.js supports it natively (≥ v11.7.0).
For the Node.js versions that not support brotli natively, it's not enabled by default, if you need it we recommend to install [`iltorb`](https://www.npmjs.com/package/iltorb) and pass it as option.
For Node.js versions that don’t natively support Brotli, it's not enabled by default. If you need it, we recommend installing [`iltorb`](https://www.npmjs.com/package/iltorb) and passing it to the `brotli` option:

@@ -95,6 +95,6 @@ ```javascript

### Disable compression by header
You can selectively disable the response compression by using the `x-no-compression` header in the request.
You can selectively disable response compression by using the `x-no-compression` header in the request.
### Inflate pre-compressed bodies for clients that do not support compression
Optional feature to inflate pre-compressed data if the client doesn't include one of the supported compression types in its `Accept-Encoding` header.
Optional feature to inflate pre-compressed data if the client doesn't include one of the supported compression types in its `accept-encoding` header.
```javascript

@@ -112,4 +112,16 @@ fastify.register(

### Customize encoding priority
By default, `fastify-compress` prioritizes compression as described [at the beginning of §Usage](#usage). You can change that by passing an array of compression tokens to the `encodings` option:
```javascript
fastify.register(
require('fastify-compress'),
// Only support gzip and deflate, and prefer deflate to gzip
{ encodings: ['deflate', 'gzip'] }
)
```
## Note
Please have in mind that in large scale scenarios, you should use a proxy like Nginx to handle response-compression.
Please note that in large-scale scenarios, you should use a proxy like Nginx to handle response compression.

@@ -116,0 +128,0 @@ ## Acknowledgements

@@ -92,2 +92,26 @@ 'use strict'

test('should send a gzipped data if header case varied', t => {
t.plan(3)
const fastify = Fastify()
fastify.register(compressPlugin, { global: false })
fastify.get('/', (req, reply) => {
reply.type('text/plain').compress(createReadStream('./package.json'))
})
fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'GZiP'
}
}, (err, res) => {
t.error(err)
t.strictEqual(res.headers['content-encoding'], 'gzip')
const file = readFileSync('./package.json', 'utf8')
const payload = zlib.gunzipSync(res.rawPayload)
t.strictEqual(payload.toString('utf-8'), file)
})
})
test('should send a gzipped data with custom zlib', t => {

@@ -262,3 +286,3 @@ t.plan(4)

headers: {
'accept-encoding': 'hello,br'
'accept-encoding': 'hello,br,gzip'
}

@@ -274,3 +298,3 @@ }, (err, res) => {

test('Unsupported encoding', t => {
test('should send uncompressed if unsupported encoding', t => {
t.plan(3)

@@ -292,13 +316,9 @@ const fastify = Fastify()

t.error(err)
const payload = JSON.parse(res.payload)
t.strictEqual(res.statusCode, 406)
t.deepEqual({
error: 'Not Acceptable',
message: 'Unsupported encoding',
statusCode: 406
}, payload)
t.strictEqual(res.statusCode, 200)
const file = readFileSync('./package.json', 'utf8')
t.strictEqual(res.payload, file)
})
})
test('Unsupported encoding with quality value', t => {
test('should send uncompressed if unsupported encoding with quality value', t => {
t.plan(3)

@@ -320,9 +340,5 @@ const fastify = Fastify()

t.error(err)
const payload = JSON.parse(res.payload)
t.strictEqual(res.statusCode, 406)
t.deepEqual({
error: 'Not Acceptable',
message: 'Unsupported encoding',
statusCode: 406
}, payload)
t.strictEqual(res.statusCode, 200)
const file = readFileSync('./package.json', 'utf8')
t.strictEqual(res.payload, file)
})

@@ -437,3 +453,3 @@ })

test('Should send 406 error on invalid accept encoding', t => {
test('Should send uncompressed on invalid accept encoding', t => {
t.plan(3)

@@ -456,9 +472,4 @@ const fastify = Fastify()

t.error(err)
const payload = JSON.parse(res.payload)
t.strictEqual(res.statusCode, 406)
t.deepEqual({
error: 'Not Acceptable',
message: 'Unsupported encoding',
statusCode: 406
}, payload)
t.strictEqual(res.statusCode, 200)
t.strictEqual(res.payload, 'something')
})

@@ -513,2 +524,25 @@ })

test('Should compress buffer (gzip) if header case varied', t => {
t.plan(2)
const fastify = Fastify()
fastify.register(compressPlugin, { global: false, threshold: 0 })
const buf = Buffer.from('hello world')
fastify.get('/', (req, reply) => {
reply.compress(buf)
})
fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'GzIp'
}
}, (err, res) => {
t.error(err)
const payload = zlib.gunzipSync(res.rawPayload)
t.strictEqual(payload.toString('utf-8'), buf.toString())
})
})
test('Should compress buffer (deflate)', t => {

@@ -608,2 +642,25 @@ t.plan(2)

test('Should compress buffer (gzip) with varied header case - global', t => {
t.plan(2)
const fastify = Fastify()
fastify.register(compressPlugin, { threshold: 0 })
const buf = Buffer.from('hello world')
fastify.get('/', (req, reply) => {
reply.send(buf)
})
fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'gZIP'
}
}, (err, res) => {
t.error(err)
const payload = zlib.gunzipSync(res.rawPayload)
t.strictEqual(payload.toString('utf-8'), buf.toString())
})
})
test('Should compress buffer (deflate) - global', t => {

@@ -1398,1 +1455,47 @@ t.plan(2)

})
test('Should only use `encodings` if passed', t => {
t.plan(3)
const fastify = Fastify()
fastify.register(compressPlugin, { encodings: ['deflate'] })
fastify.get('/', (req, reply) => {
reply.send(createReadStream('./package.json'))
})
fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'br,gzip,deflate'
}
}, (err, res) => {
t.error(err)
t.strictEqual(res.headers['content-encoding'], 'deflate')
t.strictEqual(res.statusCode, 200)
})
})
test('Should error if `encodings` array is empty', t => {
t.plan(1)
const fastify = Fastify()
fastify.register(compressPlugin, { encodings: [] })
fastify.ready(err => {
t.ok(err instanceof Error)
})
})
test('Should error if no entries in `encodings` are supported', t => {
t.plan(1)
const fastify = Fastify()
fastify.register(compressPlugin, {
encodings: ['(not-a-real-encoding)']
})
fastify.ready(err => {
t.ok(err instanceof Error)
})
})

@@ -15,3 +15,4 @@ import * as fastify from 'fastify'

inflateIfDeflated: true,
customTypes: /x-protobuf$/
customTypes: /x-protobuf$/,
encodings: ['gzip', 'br', 'identity', 'deflate']
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc