Middleware
Middleware functions are executed before the route handler. They have access to the request Context and the next function.
Creating Middleware
Implement the CarnoMiddleware interface. The class should be decorated with @Service() (or @Injectable()) so dependencies can be injected.
import { Service, CarnoMiddleware, Context, CarnoClosure } from '@carno.js/core';
@Service()
export class AuthMiddleware implements CarnoMiddleware {
async handle(context: Context, next: CarnoClosure) {
const token = context.headers.get('authorization');
if (!token) {
context.setResponseStatus(401);
return; // Stop execution (don't call next)
}
// Pass control to the next middleware or route handler
next();
}
}
Applying Middleware
Controller Level
Apply middleware to all routes in a controller.
import { Middleware, Controller } from '@carno.js/core';
import { AuthMiddleware } from './auth.middleware';
@Controller()
@Middleware(AuthMiddleware)
export class UsersController {
// ...
}
Route Level
Apply middleware to a specific route.
import { Middleware, Get } from '@carno.js/core';
export class UsersController {
@Get()
@Middleware(AuthMiddleware)
findAll() {
return [];
}
}
Global Middleware
Apply middleware to every route in the application via the Carno configuration.
new Carno({
globalMiddlewares: [AuthMiddleware],
providers: [AuthMiddleware] // Don't forget to register the provider!
}).listen();
Middleware Execution Order
- Global Middleware: Executed first, in the order defined in the array.
- Controller Middleware: Executed next.
- Route Middleware: Executed last, before the handler.
Dependency Injection in Middleware
Since middleware classes are providers, you can inject other services into them.
@Service()
export class LoggerMiddleware implements CarnoMiddleware {
constructor(private logger: LoggerService) {}
handle(context: Context, next: CarnoClosure) {
this.logger.info(`Request to ${context.req.url}`);
next();
}
}