Middleware

Logic that runs around a route handler — before it, after it, or instead of it.

A Middleware receives the Context and a next function. What runs before await next() happens on the way in; what runs after it happens on the way out, with the downstream result in hand. Returning early instead of calling next() short-circuits the chain, which is how authentication rejects a request without the route handler ever running.

Constructing one registers it on the nearest App, which folds it into each targeted route's chain at compile time via composeHandlerChain. Targeting is by route id, but Middleware.useOn accepts routes and Controller instances directly and resolves the ids itself.

import { Middleware } from "@ozanarslan/corpus";

new Middleware({
	useOn: usersController,
	handler: async (c, next) => {
		const started = performance.now();
		const result = await next();
		c.res.headers.set("X-Response-Time", performance.now() - started);
		return result;
	},
});
Contents
  1. Middleware
  2. MiddlewareDefinition
  3. MiddlewareUseOn
  4. MiddlewareHandler

Middleware

class

class Middleware

A handler registered to run around some or all of an app's routes.

Middlewares execute in the order App.findMiddlewares returns them: global ones first, then route-specific ones, then the route handler. Since the chain nests, a global middleware wraps everything after it — its post-next() code runs last.

Targeting a route id that no route claims is not an error, but the middleware will never run; App.warnUnmatchedMiddlewares logs a warning at startup when that happens.

Middleware.constructor()

constructor();
constructor(definition: MiddlewareDefinition);
constructor(definition?: MiddlewareDefinition)

Creates a middleware for subclasses, which declare Middleware.handler and Middleware.useOn as class fields and call Middleware.register themselves.

Creates a middleware and registers it on the nearest App.

Parameters

Middleware.register()

register(): void

Registers this middleware on the nearest App through App.addMiddleware. Called by the constructor.

Registration order relative to routes does not matter — targets are resolved to ids here, and the app only matches them when it compiles routes.

Middleware.useOn

useOn: MiddlewareUseOn;

What this middleware applies to. Defaults to "*", meaning every route on the app.

Middleware.handler

handler!: MiddlewareHandler

The function that runs when a targeted route is hit.

Middleware.routeIds

get routeIds(): Array<string>

The route ids resolved from Middleware.useOn, which App.addMiddleware indexes the middleware under.

Each target contributes its ids: a route its own, a Controller all of Controller.routeIds, and a string itself. Duplicates are collapsed, so a route listed both directly and through its controller is still wrapped once.

Returns — The ids, or ["*"] for a global middleware.

MiddlewareDefinition

type

type MiddlewareDefinition = {
	/** What the middleware applies to. Defaults to `"*"` — every route. */ useOn?: MiddlewareUseOn;
	/** The [MiddlewareHandler](#middlewarehandler) to run. */ handler: MiddlewareHandler;
};

Construction arguments for a Middleware.

NameDescription
useOnWhat the middleware applies to. Defaults to "*" — every route.
handlerThe MiddlewareHandler to run.

MiddlewareUseOn

type

type MiddlewareUseOn =
	Array<RouteBase | Controller | string> | RouteBase | Controller | OrString<"*">;

What a middleware applies to.

A RouteBase targets that route, a Controller targets every route registered through it, a string targets a route id directly, and an array combines any of these. The literal "*" targets every route on the app, including requests that match none — global middlewares also run ahead of App.handleNotFound.

MiddlewareHandler

type

type MiddlewareHandler<R = unknown> = (
	context: Context,
	next: () => MaybePromise<R>,
) => MaybePromise<R>;

A middleware's handler function. Like a ContextHandler, but with the rest of the chain passed in.

What the return value means is resolved by composeHandlerChain: a returned value short-circuits the chain, undefined after calling next() passes the downstream result through, and undefined without calling next() lets the chain continue anyway.

Type parameters

Parameters

Returns — The response value, or undefined to defer to the chain.