# NestJS Middleware: Everything You Need to Know

When developing scalable server-side [applications](https://bytescrum.com/), NestJS is a powerful framework that leverages TypeScript and takes inspiration from Angular to provide a modular architecture. One of the crucial aspects of building robust applications is understanding and utilizing middleware effectively. This blog will dive into what middleware is, how it works in NestJS, and how you can implement it in your applications.

## What is Middleware?

Middleware functions are functions that have access to the request and response objects, and the <mark>next()</mark> middleware function in the application’s request-response cycle. These functions can execute any code, make changes to the request and response objects, end the request-response cycle, and call the next middleware function.

Middleware in NestJS can be used for various tasks, such as:

* Logging requests
    
* Authenticating users
    
* Parsing request bodies
    
* Implementing CORS (Cross-Origin Resource Sharing)
    
* Error handling
    

## How Middleware Works in NestJS

In NestJS, middleware can be applied globally, at the module level, or for specific routes. Middleware in NestJS is very similar to Express middleware, making it familiar for those who have worked with Express.

### Types of Middleware in NestJS

1. **Global Middleware**: Applies to all routes in the application.
    
2. **Route Middleware**: Applies to specific routes.
    
3. **Module Middleware**: Applies to all routes in a specific module.
    

## Creating Middleware in NestJS

To create middleware in NestJS, you need to implement the `NestMiddleware` interface or use a plain function. Here’s a step-by-step guide to creating and applying middleware in NestJS.

### Step 1: Create Middleware

First, let’s create a simple logging middleware that logs the request method and URL.

```typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`${req.method} ${req.url}`);
    next();
  }
}
```

### Step 2: Apply Middleware

#### Global Middleware

To apply middleware globally, you need to use the `configure` method in the main application module.

```typescript
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerMiddleware } from './logger.middleware';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*'); // Apply to all routes
  }
}
```

#### Route Middleware

To apply middleware to specific routes, you can specify the routes in the `forRoutes` method.

```typescript
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerMiddleware } from './logger.middleware';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('cats'); // Apply to routes that match 'cats'
  }
}
```

#### Module Middleware

To apply middleware to all routes within a specific module, you include the middleware configuration in that module.

```typescript
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { LoggerMiddleware } from './logger.middleware';

@Module({
  controllers: [CatsController],
})
export class CatsModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(CatsController); // Apply to all routes in CatsController
  }
}
```

## Practical Examples of Middleware

### Authentication Middleware

Here’s an example of an authentication middleware that checks if a user is authenticated.

```typescript
import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class AuthMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    if (!req.headers.authorization) {
      throw new UnauthorizedException('You are not authorized.');
    }
    next();
  }
}
```

### Error Handling Middleware

An error-handling middleware that catches and processes errors can also be implemented.

```typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class ErrorHandlingMiddleware implements NestMiddleware {
  use(err: any, req: Request, res: Response, next: NextFunction) {
    console.error(err.stack);
    res.status(500).send('Something broke!');
  }
}
```

<details data-node-type="hn-details-summary"><summary>Conclusion</summary><div data-type="detailsContent">Middleware is a powerful feature in NestJS that allows you to handle requests and responses effectively. Whether you need to log requests, handle authentication, or manage errors, understanding how to create and apply middleware can significantly enhance your application.</div></details>

By following the steps outlined in this guide, you can create and implement middleware in your NestJS applications to handle a variety of tasks, making your application more robust and maintainable. Happy coding!
