/fastify-throttle

Throttle the download speed of a request

Primary LanguageJavaScript

@fastify/throttle

CI NPM version js-standard-style

Throttle the download speed of a request.

Install

npm i @fastify/throttle

Usage

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')
})

Options

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

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:

(elapsedTime: number, bytes: number) => number

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 (elapsedTime, bytes) {
          if (elapsedTime < 2) {
            return 0
          } else {
            return Infinity
          }
        }
      }
    }
  }, (req, reply) => {
    reply.send(createReadStream(resolve(__dirname, __filename)))
  })

  fastify.listen({ port: 3000 })

License

MIT