2.0.1 • Published 5 months ago

@fastify/throttle v2.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

@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.

HeaderDescriptionDefault
bytesPerSecondThe allowed bytes per second, number or a function16384
streamPayloadsThrottle the payload if it is a streamtrue
bufferPayloadsThrottle the payload if it is a Bufferfalse
stringPayloadsThrottle the payload if it is a stringfalse
asyncSet to true if bytesPerSecond is a function returning a Promisefalse

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

License

MIT

2.0.1

5 months ago

2.0.0

7 months ago

1.0.0

9 months ago