Middleware in nest.js
Tags: typescript, beginners, node
Published: 2023-03-11 01:31:22

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 <span class="emoji-outer emoji-sizer"><span class="emoji-inner" style="background: url(chrome-extension://gaoflciahikhligngeccdecgfjngejlh/emoji-data/sheet_apple_32.png);background-position:61.98589894242068% 44.00705052878966%;background-size:5418.75% 5418.75%" data-codepoints="1f62c"></span></span> , 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  <span class="emoji-outer emoji-sizer"><span class="emoji-inner" style="background: url(chrome-extension://gaoflciahikhligngeccdecgfjngejlh/emoji-data/sheet_apple_32.png);background-position:59.9882491186839% 75.96944770857814%;background-size:5418.75% 5418.75%" data-codepoints="1f609"></span></span>

```javascript
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,

```javascript
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 

```typescript
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

```typescript
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 

```javascript
@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

```javascript
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<span class="emoji-outer emoji-sizer"><span class="emoji-inner" style="background: url(chrome-extension://gaoflciahikhligngeccdecgfjngejlh/emoji-data/sheet_apple_32.png);background-position:61.98589894242068% 87.95534665099882%;background-size:5418.75% 5418.75%" data-codepoints="1f642"></span></span>