DEV Community

Cover image for Middleware in nest.js
djibril mugisho
djibril mugisho

Posted on • Edited on

Middleware in nest.js

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
Enter fullscreen mode Exit fullscreen mode

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 " });
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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')
  }
}
Enter fullscreen mode Exit fullscreen mode

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 })
  }
}
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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

Top comments (2)

Collapse
 
larbi_benyakhou_1cfec2bf2 profile image
larbi benyakhou

Thanks

Collapse
 
white_shadow_e78b87af5738 profile image
White Shadow

Thank you. But the most important section is missed. I think code that enable the middleware should be in the main.ts file. Here are some code that enables the middleware in the NestJs.

First, install the morgan package using NPM
npm install morgan

And then set up middleware
//main.ts
import morgan from 'morgan'

app.use(morgan('dev'))