Skip to main content
The @talosjs/middleware component is a pipeline framework for intercepting requests. Each middleware implements the IMiddleware interface (or ISocketMiddleware for WebSockets), receives the request context, and returns it, modified or unchanged, to the next stage. Register a class with @decorator.middleware() and the container resolves it; the app runs registered middleware in order before the controller handles the request.

The pipeline model

Every HTTP middleware implements IMiddleware with a single handler(context) method, which keeps them predictable to write, read, and test. The same context object flows through every stage, carrying the request, response, and headers, and you read and mutate it in place. Write a response (context.response.json(...) or context.response.exception(...)) to halt the pipeline before the controller, which is how auth checks and rate limits short-circuit. WebSocket interception works the same way: ISocketMiddleware mirrors the HTTP shape against the socket context for connection-time checks. Because every middleware is decorated and resolved through dependency injection, you can constructor-inject env, loggers, or services.

How it works

The app holds an ordered list of middleware. For each incoming request it builds a context and passes it through every registered middleware in sequence, then to the matched controller. Each handler returns the context to continue the chain. A middleware runs “before” by doing its work at the top of handler and then returning context. Since the same context object carries the response, middleware can also shape the outgoing response (set headers, status) before returning. The contract comes down to one rule: always return the context so the chain continues.

Decorator and usage

@decorator.middleware()

Registers a class as middleware with the dependency injection container. It accepts an optional scope (defaults to singleton). The class must implement IMiddleware (HTTP) or ISocketMiddleware (WebSocket).
A real HTTP middleware reads the context, optionally writes to the response to short-circuit, and returns the context:
Inject dependencies through the constructor; the container provides them when it resolves the middleware:
WebSocket middleware uses the same decorator and shape against the socket context via ISocketMiddleware:

Writing solid middleware

The chain continues only when handler returns the context object, so always return it and never return a new object in its place. Read from and write to the shared context in place, attaching resolved state (like a user) for downstream middleware and the controller to use. Write a response only when you actually mean to stop the pipeline, as on auth failures or rate limits; otherwise fall through. Keep each middleware to one concern (auth, logging, rate limiting) so the registration order reads as a clear pipeline. Order matters: middleware runs in registration order, so put cross-cutting concerns like logging and headers ahead of guards that may short-circuit. And pull env, loggers, and services through the constructor with @inject rather than constructing them inside handler.

CLI command

Scaffold a middleware class and its test file with the generator. It writes the class under modules/<module>/src/middlewares/<Name>Middleware.ts, adds a matching test, and installs @talosjs/middleware if it is missing.
The generated class is a ready-to-implement IMiddleware stub:
A socket middleware stub is identical except it imports ContextType from @talosjs/socket. After generating, register the class in the middlewares array of your module. See middleware:create for the full command reference.

Use with Claude and Codex

The generator ships a matching middleware:create skill. It runs the scaffold, then guides your AI agent through completing the middleware: implementing handler with real logic (auth checks, logging, header injection), wiring dependencies through the constructor, and registering the class in its module. Initialize the skills once for your agent.
Then ask Claude in natural language. It maps the request to the generator, runs it, and fills in the implementation:
Prompt
For example, the prompt above maps to middleware:create --name=Logging, then implements handler to log the request method and path before returning the context.