Skip to content

Latest commit

 

History

History
129 lines (91 loc) · 4.91 KB

File metadata and controls

129 lines (91 loc) · 4.91 KB

@jnode/server-ratelimit

Official rate limit package for JNS.

Installation

npm i @jnode/server-ratelimit

Quick start

Import

const { createServer, routerConstructors: r, handlerConstructors: h } = require('@jnode/server');
const { routerConstructors: rr } = require('@jnode/server-ratelimit');

Start a rate-limited server

const server = createServer(
  // apply rate limit: 5 requests per 5 seconds
  rr.RateLimit(
    // pass: what to do if the request is within limit
    h.Text('Welcome! You are not rate-limited.'),
    // fail: what to do if the request exceeds limit (default is 429)
    h.Text('Too many requests, please try again later.', { statusCode: 429 }),
    // limiter configuration
    'tb: 5, 5s'
  )
);

server.listen(8080);

Advanced configuration

const server = createServer(
  rr.RateLimit(
    h.Text('API accessed.'),
    429,
    // Configuration: 10 reqs / 1 min, GC every 5 mins, 
    // auto GC when > 2000 users, force GC every 2 hours
    'tb: 10, 1m, 5m, 2000, 2h',
    // identify by IP address specifically
    'address',
    { disableRetryHeader: false }
  )
);

server.listen(8080);

How it works?

@jnode/server-ratelimit provides a router that acts as a gatekeeper.

When a request arrives:

  1. It identifies the client (using the by parameter, usually by IP address).
  2. It checks the limiter (currently using a Token Bucket algorithm) to see if the client has tokens available.
  3. If tokens are available, it consumes one and returns the pass router/handler.
  4. If no tokens remain, it returns the fail router/handler and optionally sets the Retry-After header.

Reference

Router: RateLimit(pass[, fail, limiter, by, options])

  • pass router | handler-extended The router or handler to use if the rate limit has not been reached.
  • fail router | handler-extended The router or handler to use if the rate limit is exceeded. Default: 429.
  • limiter <string> | <Function>
    • If string, format is type: args. Currently supported type is tb (Token Bucket).
    • If function, signature is (identity) => true | number. Returns true to pass, or a number representing seconds until retry to fail.
    • Default: 'tb: 5, 5s'.
  • by <string> | <Function> How to identify the client.
    • 'auto': Uses ctx.identity.id if available, otherwise ctx.identity.address.
    • 'address': Uses ctx.identity.address.
    • Custom Function: (env, ctx) => identityString.
    • Default: 'auto'.
  • options <Object>
    • disableRetryHeader <boolean> If true, the Retry-After header will not be added to the response on failure. Default: false.

Token Bucket (tb) string format

The limiter string for tb follows this comma-separated argument structure: 'tb: tokens, resetTime, gcTime, autoGC, forceGCTime, gcChunkSize'

  • tokens: Number of requests allowed per period.
  • resetTime: Time duration before tokens refill (e.g., '5s', '1m', '1h').
  • gcTime: How often to run garbage collection for inactive identities. Default: '10m'.
  • autoGC: Max number of tracked identities before triggering GC. Default: 1000.
  • forceGCTime: Maximum time to wait before forcing GC regardless of autoGC. Default: '1h'.
  • gcChunkSize: Number of records to process per GC tick (to prevent blocking the event loop). Default: 500.

Time units supported: ms, s, m, h, d. If no unit is provided, it defaults to seconds.

identifyFunctions

A map of built-in identification strategies.

  • auto: (env, ctx) => ctx.identity.id ?? ctx.identity.address
  • address: (env, ctx) => ctx.identity.address

limiters

A map of available limiter classes.

  • tb: TokenBucketLimiter class.

Class: RateLimitRouter

The class used to create the rate limit router.

new RateLimitRouter(pass[, fail, limiter, by, options])

Same arguments as routerConstructors.RateLimit.

rateLimitRouter.route(env, ctx)

Performs the rate limit check and returns either the pass or fail result.