Middlewares
Middlewares process requests in a pipeline before they reach your controllers. They handle cross-cutting concerns like authentication, logging, validation, and request transformation.
Overview
YasuiJS supports two types of middlewares:
- Class-based middlewares using the
@Middleware()
decorator - Express RequestHandler functions for compatibility with existing Express middlewares
Middlewares can be applied at three levels with different execution priorities:
- Application level - Applied to all requests
- Controller level - Applied to all routes in a controller
- Endpoint level - Applied to specific routes
import { Middleware } from 'yasui';
@Middleware()
export class LoggingMiddleware {
use() {
console.log('Request received');
}
}
Class-based Middlewares
Middleware Decorator
The @Middleware()
decorator marks a class as middleware. The class must implement a use()
method. You can optionally implement the IMiddleware
interface provided by YasuiJS to enforce the method signature.
import { Middleware, IMiddleware, Request, Response, Req, Res } from 'yasui';
@Middleware()
export class AuthMiddleware implements IMiddleware {
use(
@Req() req: Request,
@Res() res: Response
) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Validate token logic here
// Will continue to next middleware or controller logic if you return nothing/void
}
}
Parameter Decorators in Middlewares
Middlewares can use the same parameter decorators as controllers and benefit from automatic error catching too:
@Middleware()
export class ValidationMiddleware {
use(
@Body() body: any,
@Query('validate') shouldValidate: boolean,
@Header('content-type') contentType: string
) {
if (shouldValidate && !this.isValid(body)) {
throw new HttpError(400, 'Invalid request data');
}
}
private isValid(data: any): boolean {
// Validation logic
return true;
}
}
Automatic Type Casting: All parameter decorators in middlewares benefit from the same automatic type casting as controllers. Parameters are cast to their specified types before middleware execution.
Dependency Injection
As Middleware classes act like Controllers, they also allow dependency injection in the same way:
@Middleware()
export class LoggingMiddleware {
constructor (
private validationService: ValidationService, // Standard injection
@Inject('CONFIG') private config: AppConfig, // Pre-registered custom injection
) {}
use(
@Body() body: any,
@Inject() anotherService: AnotherService, // Same at method level
) {
if (!this.validationService.isValid(body)) {
throw new HttpError(400, 'Invalid request data');
}
}
}
Express RequestHandler Middlewares
You can use standard Express middleware functions directly:
import cors from 'cors';
import helmet from 'helmet';
yasui.createServer({
middlewares: [
cors(),
helmet(),
]
});
Middleware Usage Levels
Application Level
Applied to all requests across your entire application:
yasui.createServer({
controllers: [UserController],
middlewares: [LoggingMiddleware, SecurityMiddleware]
});
Controller Level
Applied to all routes within a specific controller:
// Single middleware
@Controller('/api/users', AuthMiddleware)
export class UserController {
// All routes require authentication
}
// Multiple middlewares
@Controller('/api/admin', AuthMiddleware, ValidationMiddleware)
export class AdminController {
// All routes have auth + validation
}
Endpoint Level
Applied to specific routes only:
@Controller('/api/users')
export class UserController {
@Get('/')
getUsers() {
// No middleware
}
@Post('/', ValidationMiddleware)
createUser() {
// Only validation middleware
}
@Delete('/:id', AuthMiddleware, ValidationMiddleware)
deleteUser() {
// Both auth and validation middlewares
}
}
Execution Order
Middlewares execute in this order:
- Application middlewares (in registration order)
- Controller middlewares (in declaration order)
- Endpoint middlewares (in declaration order)
- Controller method
// Execution order example:
yasui.createServer({
middlewares: [GlobalMiddleware] // 1. First
});
@Controller('/users', ControllerMiddleware) // 2. Second
export class UserController {
@Post('/', EndpointMiddleware) // 3. Third
createUser() {
// 4. Finally the controller method
}
}