Middleware runs before your route handler and can inspect or modify the request,
or reject it outright.
npx avleon make:middleware logger
The command generates:
src/middlewares/logger.middleware.ts
import { AppMiddleware, AvleonMiddleware, IRequest, IResponse } from '@avleon/core';
@AppMiddleware
export class LoggerMiddleware extends AvleonMiddleware {
/**
* Return the request to continue, or throw to stop the pipeline.
*/
async invoke(req: IRequest, res?: IResponse) {
console.log('url:', req.url);
return req;
}
}
A middleware extends AvleonMiddleware and implements invoke. Returning the
request continues the pipeline; throwing an HttpExceptions error stops it:
import { AppMiddleware, AvleonMiddleware, IRequest, HttpExceptions } from '@avleon/core';
@AppMiddleware
export class ApiKeyMiddleware extends AvleonMiddleware {
async invoke(req: IRequest) {
if (req.headers['x-api-key'] !== process.env.API_KEY) {
throw HttpExceptions.unauthorized('Invalid API key');
}
return req;
}
}
Middleware can be applied at three levels.
Runs for every request. Note the plural — useMiddlewares:
app.ts
import { Avleon } from '@avleon/core';
import { LoggerMiddleware } from './middlewares/logger.middleware';
const app = Avleon.createApplication();
app.useMiddlewares([LoggerMiddleware]);
export default app;
Runs for every route on that controller:
import { ApiController, Get, UseMiddleware } from '@avleon/core';
import { LoggerMiddleware } from '../middlewares/logger.middleware';
@UseMiddleware(LoggerMiddleware)
@ApiController('/home')
export class HomeController {
@Get()
sayHello() {
return 'Hello';
}
}
Runs for a single route:
import { ApiController, Get, UseMiddleware } from '@avleon/core';
import { LoggerMiddleware } from '../middlewares/logger.middleware';
@ApiController('/home')
export class HomeController {
@UseMiddleware(LoggerMiddleware)
@Get()
sayHello() {
return 'Hello';
}
}
UseMiddleware also accepts an array:
@UseMiddleware([LoggerMiddleware, ApiKeyMiddleware])
Note: @UseMiddleware must sit above @ApiController on a class, and above the route
decorator on a method — decorators apply bottom-up.