middleware/validate

module:middleware/validate

Description:
  • Validation and Rate Limiter Middleware

    As oppose to the limiter by path this middleware validates first the params/query/body parameters and returns an error immediately, then if configured can check rate limits for the matching method, path and parameter behaving similar to the module:api/limiter.

    For example this is useful and universally checked in case of multi-tenant environment when each tenant is distinguished by path/query/body property like accountId, clientId or else.

    Validating common global parameters upfront with rate limits allows the actual business handlers to avoid boilerplate checks and focus only on specific logic instead and allows scaling and restrictions to be applied in real time without code changes.

    Because the router does not validate params parts in the path, only extracts, this is a way to enforce path parameters to a particular type or format.

    Validation config

    middleware-validate-params, middleware-validate-query, middleware-validate-body config parameters are configured, only matched methods and paths are checked, each parameter will be validated using module:lib/validate.

    Errors are returned immediately.

    Validated and converted values are placed back into params/query/body, this allows subsequent middleware to reuse already validated and converted values immediately.

    Path params are kept as strings.

    Rate limiting

    If rate limiting is required set the rate and other parameters must be placed with rate prefix, like rate_interval, rate_ttl, rate_max, rate_queue...`, all valid parameters for module:api/limiter can be placed in the config.

    The path rating logic is the same as in the limiter middleware.

    Configurations with the same path and method(s) are merged into a single object, i.e. changes are accumulated, to clear values explicit values must be set like 0 or null.

    To rate limit by session ID or authenticated user is supported if validation succeded:

    • rate_session rates the session id from the header
    • rate_user rates verified user id

    By default this middleware is executed after the users middleware, i.e. user/session verification must succeed but still in case of missing session or user id the rating will use undefined, i.e. it will rate all requests without sessions globally.

    NOTE: Named/wildcard parameters in the validate middleware paths must match the actual paths in the custom middleware to reuse the same validated parameters.

    Examples

    # Validate accountId for all /account requests and allow 100 req/s only
    middleware-validate-params-get,post-accountId-/account/:accountId/* = type:int,strict:true,min:100000,required:true,rate:100
    
    # Validate clientId to be a number in the query for all /api requests and allow 100 req/s only
    middleware-validate-query-get,post-clientId-/api/* = type:int,max:32,required:true,rate:100,rate_interval:30000
    
    
    # Validate login email and limit to 2 req per minute, increase delay
    middleware-validate-body-post-login-/login = type:email,max:128,required:true
    
    # Nerge with previous entry, add rate limiting to validation
    middleware-validate-body-post-login-/login = rate:2,rate_interval:60000,rate_multiplier:1.5
    
    
    # Use JSON format for regexp validation or complex structures
    middleware-validate-body-post-ssn-/register = { "required": true, "regexp": "^[0-9]{3}-[0-9]{2}-[0-9]{4}$", "errmsg": "Valid SSN is required in NNN-NN-NNNN format" }
    
    
    # Rate limit all /admin/XXX requests by session id and XXX part to allow only 10 per 30s
    middleware-validate-params-*-0-/admin/* = rate:10,rate_interval:30000,rate_session:true
    
    # Rate limit all /admin/XXX requests by user and XXX part to allow only 10 per 30s
    middleware-validate-params-*-0-/admin/* = rate:10,rate_interval:30000,rate_user:true
    
    

    Global mode

    Enable via middleware-validate-enable = true to dynamically check every request path, this allows to add more or modify routes without restarting

    Fixed config mode

    To enable just what is in the config on start and ignore new routes, modifying existing routes is still supported

    middleware-validate-enable = fixed
    
Source:

Members

(static) args :Array.<ConfigOptions>

Source:
Default Value:
  • [
      {
        "name": "enable",
        "descr": "Enable the middlware, 'true' means dynamicaly check all requests, 'fixed' means set routes from the config on start"
      },
      {
        "name": "(query|body|params)-([a-z,*]+)-([a-zA-Z0-9_]+)-(/.+)",
        "type": "map",
        "no_camel": 1,
        "ephemeral": 1,
        "logger": "error",
        "onupdate": "",
        "descr": "Validate and optionally rate limit by a parameter from query/body/params by method and path",
        "example": "middleware-validate-query-*-accountId-/api/* = type:int,required:true,rate:10,rate_interval:30000"
      },
      {
        "name": "reset",
        "type": "callback",
        "callback": "",
        "descr": "Reset all rules"
      },
      {
        "name": "priority",
        "type": "int",
        "descr": "Add routes with this priority sorting number, for config mode only"
      }
    ]

Methods

(static) configureMiddleware()

Description:
  • Start global middleware if enabled

Source:

(static) handle(context, next)

Source:
Parameters:
Name Type Description
context RequestContext
next function()
Example
const { api, middleware } = require("backendjs");
const { validate } = middleware;

api.app.post("*", validate)

api.app.post("/account/*", validate)

api.app.post("/account", {
    body: {
        accountId: { type: "int", required: true, rate: 100 },
        amount: { type: "number", max: 1000 }
    }
}, handle: validate.handle })