Middleware in nest.js
Djibril Mug
11 Mar 2023
4 min read
Before writing any line of code let's first define a middleware function in nest.js, a middleware function is a function that gets called before the route handler function, middleware functions have access to the request and response objects, a good definition, right? But what does that mean? Simply a middleware function is a function that gets triggered before the main request function, it can end the request life cycle or continue the request life cycle, not ending and not continuing will leave the request hanging which is a disaster for users' experience , a middleware function can modify the request object such as adding data reaching to a database just do everything that you can do in any normal function
Too much talking let's see that in action
new nest middleware
as you can see I have nest installed globally on my machine if you face any problems while creating the application please use the following guide from the official nest.js website https://docs.nestjs.com/
**Basic middleware ** For creating nest.js middleware you can use the class approach or use the function approach but for this example, we shall use the class base approach which is recommended by the nest.js team, in the example below we create a middleware function that takes the greeting string passed to our request body and check if the greeting is equal to hello, if the greeting is not hello the middleware function returns the request, and if the greeting passed into the request body is hello then the middleware function continues the request cycle and add a new data to our request body,
import { Injectable, NestMiddleware } from "@nestjs/common";
import { Request, Response, NextFunction } from "express";
@Injectable()
export class greetingMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
if (req.body.greeting === 'hello') {
req.body.randomNumber = Math.random();
next()
} else {
return res.status(403).json({ message: "no greeting passed or not equal to hello " });
}
}
}
Dependency injection Like controllers and providers, middleware can also inject dependencies that are in the same module
Applying middlewares
As me, you may think that middlewares are placed in the @module
decorator but that is not the case, instead, we set them up using the configure()
method of the module class, modules that contain middlewares have to implement the NestModule
interface, let us see how to apply our greetingMiddlewar
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { greetingMiddleware } from './middleware/basicMiddleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(greetingMiddleware).forRoutes('greeting')
}
}
In the example above we apply the greetingMiddlewar
to the greeting route using the forRootes()
method, we can also restrict the middleware to specific request methods by passing an object to the forRootes
method containing the route path and the method, note that you are not restricted to one route you can pass your middleware to more than one route or pass it to the entire controller in the following example we see how to apply our middleware with a specific request method
import { Module, NestModule, MiddlewareConsumer,RequestMethod } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { greetingMiddleware } from './middleware/basicMiddleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(greetingMiddleware).forRoutes({ path: 'greeting', method: RequestMethod.GET })
}
}
while using this method please do not forget to import RequestMethod
it helps us to reference the targeted request method.
Applying to the entire controller
In some cases you may want to pass your middleware to all routes available in your @controller
, for doing that you need to pass your imported controller into the forRoot
method as we did with routes
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(greetingMiddleware).forRoutes(AppController);
}
}
Multiple middlewares
You may also want to pass multiple middlewares that run sequentially, for having that in place you need to separate them with comma in the apply
method, the given example is down bellow
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(first(),second()).forRoutes(AppController);
}
}
conclusion Middleware functions are very important concepts that every back-end developer should know and truly understand, you will probably need them in any back-end application you will have to build.
Thanks for reading and don't forget to follow if you find this content useful