Throttle the download speed of a request.
npm i @fastify/throttle
Register the plugin and, if necessary, pass custom options.
This plugin will add an onSend
hook to the Fastify instance, which will throttle the download speed of the response.
import Fastify from 'fastify'
const fastify = Fastify()
await fastify.register(import('@fastify/throttle'), {
bytesPerSecond: 1024 * 1024, // 1MB/s
streamPayloads: true, // throttle the payload if it is a stream
bufferPayloads: true, // throttle the payload if it is a Buffer
stringPayloads: true // throttle the payload if it is a string
})
fastify.get('/', (request, reply) => {
reply.send({ hello: 'world' })
})
fastify.listen({ port: 3000 }, err => {
if (err) {
throw err
}
console.log('Server listening at http://localhost:3000')
})
You can pass the following options during the plugin registration:
await fastify.register(import('@fastify/throttle'), {
bytesPerSecond: 1000, // 1000 bytes per second
streamPayloads: true, // throttle the payload if it is a stream
bufferPayloads: true, // throttle the payload if it is a Buffer
stringPayloads: true // throttle the payload if it is a string
})
You can define the throttling globally as plugin options or per route options. The throttle options per route are the same as the plugin options.
Header | Description | Default |
---|---|---|
bytesPerSecond |
The allowed bytes per second, number or a function | 16384 |
streamPayloads |
Throttle the payload if it is a stream | true |
bufferPayloads |
Throttle the payload if it is a Buffer | false |
stringPayloads |
Throttle the payload if it is a string | false |
async |
Set to true if bytesPerSecond is a function returning a Promise | false |
Example for setting throttling globally:
const fastify = require('fastify')()
await fastify.register(import('@fastify/throttle'), {
bytesPerSecond: 1024 // 1KB/s
})
fastify.get('/', (req, reply) => {
reply.send(createReadStream(resolve(__dirname, __filename)))
})
fastify.listen({ port: 3000 })
Example for setting the throttling per route:
'use strict'
const fastify = require('fastify')()
await fastify.register(import('@fastify/throttle'))
fastify.get('/', {
config: {
throttle: {
bytesPerSecond: 1000
}
}
}, (req, reply) => {
reply.send(createReadStream(resolve(__dirname, __filename)))
})
fastify.listen({ port: 3000 })
The bytesPerSecond
option can be a number or a function. The function for bytesPerSecond
has the following TypeScript definition:
type BytesPerSecond = (request: FastifyRequest) => ((elapsedTime: number, bytes: number) => number) | Promise<((elapsedTime: number, bytes: number) => number)>
request
is the Fastify request object.
elapsedTime
is the time since the streaming started in seconds.
bytes
are the bytes already sent.
You must ensure that the return value is an integer or Infinity
.
You could, for example, delay the output by sending 0 for the first 2 seconds by defining
the bytesPerSecond
like this:
const fastify = require('fastify')()
await fastify.register(import('@fastify/throttle'))
fastify.get('/', {
config: {
throttle: {
bytesPerSecond: function bytesPerSecondfactory(request) {
// this function runs for every request
const client = request.headers['customer-id']
return function (elapsedTime, bytes) {
return CONFIG[client] * 2 // return a number of xyz
}
}
}
}
}, (req, reply) => {
reply.send(createReadStream(resolve(__dirname, __filename)))
})
fastify.listen({ port: 3000 })
The bytesPerSecond
function can be a sync function or an async function. If you provide an async function then it will be detected by the plugin. If it is a sync function returning a Promise, you must set the async
option to true
, so that the plugin knows that it should await the Promise.
const fastify = require('fastify')()
await fastify.register(import('@fastify/throttle'))
fastify.get('/', {
config: {
throttle: {
async: true,
bytesPerSecond: function bytesPerSecondfactory(request) {
// this function runs for every request
const client = request.headers['customer-id']
return Promise.resolve(function (elapsedTime, bytes) {
return CONFIG[client] * 2 // return a number of xyz
})
}
}
}
}, (req, reply) => {
reply.send(createReadStream(resolve(__dirname, __filename)))
})
fastify.listen({ port: 3000 })