How to Create a Module in NestJS That Bypasses Global Interceptors, Filters, and Guards

In developing a NestJS application, there are times when we need certain modules (such as SpecialModule) to bypass global interceptors (useGlobalInterceptors), filters (useGlobalFilters), and guards (useGlobalGuards). This article will show you how to create a special SpecialModule in NestJS by manually adding logic to global interceptors, filters, and guards to skip the routes of SpecialModule.

Step 1: Create SpecialModule

First, create a SpecialModule. You can use the Nest CLI or manually create the module files.

Terminal window
1
nest g module special

Step 2: Create SpecialController and SpecialService

Next, create a controller and service for SpecialModule.

Terminal window
1
nest g controller special
2
nest g service special

Add a simple route in special.controller.ts:

1
import { Controller, Get } from "@nestjs/common";
2
import { SpecialService } from "./special.service";
3
4
@Controller("special")
5
export class SpecialController {
6
constructor(private readonly specialService: SpecialService) {}
7
8
@Get()
9
getSpecialData() {
10
return this.specialService.getSpecialData();
11
}
12
}

Add a simple method in special.service.ts:

1
import { Injectable } from "@nestjs/common";
2
3
@Injectable()
4
export class SpecialService {
5
getSpecialData() {
6
return { message: "Special data" };
7
}
8
}

Step 3: Modify AppModule to Include SpecialModule

Ensure that AppModule includes SpecialModule:

1
import { Module } from "@nestjs/common";
2
import { SpecialModule } from "./special/special.module";
3
4
@Module({
5
imports: [SpecialModule],
6
controllers: [],
7
providers: [],
8
})
9
export class AppModule {}

Step 4: Create Global Interceptors, Filters, and Guards

Create global interceptors, filters, and guards, and add logic to skip the routes of SpecialModule.

Create a Global Interceptor

1
import {
2
Injectable,
3
NestInterceptor,
4
ExecutionContext,
5
CallHandler,
6
} from "@nestjs/common";
7
import { Observable } from "rxjs";
8
import { tap } from "rxjs/operators";
9
10
@Injectable()
11
export class GlobalInterceptor implements NestInterceptor {
12
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
13
const controller = context.getClass();
14
const controllerName = controller.name;
15
16
// Check if it belongs to SpecialController
17
if (controllerName === "SpecialController") {
18
return next.handle();
19
}
20
21
// Execute global interceptor logic
22
return next
23
.handle()
24
.pipe
25
// ... Add your global logic here
26
();
27
}
28
}

Create a Global Filter

1
import {
2
ExceptionFilter,
3
Catch,
4
ArgumentsHost,
5
HttpException,
6
} from "@nestjs/common";
7
import { Request, Response } from "express";
8
9
@Catch(HttpException)
10
export class GlobalFilter implements ExceptionFilter {
11
catch(exception: HttpException, host: ArgumentsHost) {
12
const ctx = host.switchToHttp();
13
const request = ctx.getRequest<Request>();
14
const response = ctx.getResponse<Response>();
15
const status = exception.getStatus();
16
17
const controller = host.getArgByIndex(1).constructor.name;
18
19
// Check if it belongs to SpecialController
20
if (controller === "SpecialController") {
21
return response.status(exception.getStatus()).json({
22
statusCode: status,
23
message: exception.message,
24
});
25
}
26
27
// Execute global filter logic
28
response.status(status).json({
29
statusCode: status,
30
timestamp: new Date().toISOString(),
31
path: request.url,
32
});
33
}
34
}

Create a Global Guard

1
import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
2
import { Observable } from "rxjs";
3
4
@Injectable()
5
export class GlobalGuard implements CanActivate {
6
canActivate(
7
context: ExecutionContext,
8
): boolean | Promise<boolean> | Observable<boolean> {
9
const controller = context.getClass();
10
const controllerName = controller.name;
11
12
// Check if it belongs to SpecialController
13
if (controllerName === "SpecialController") {
14
return true;
15
}
16
17
// Execute global guard logic
18
// ... Add your global logic here
19
return true;
20
}
21
}

Step 5: Apply Global Interceptors, Filters, and Guards in the Main Application

Register global interceptors, filters, and guards in main.ts:

1
import { NestFactory } from "@nestjs/core";
2
import { AppModule } from "./app.module";
3
import { GlobalInterceptor } from "./global.interceptor";
4
import { GlobalFilter } from "./global.filter";
5
import { GlobalGuard } from "./global.guard";
6
7
async function bootstrap() {
8
const app = await NestFactory.create(AppModule);
9
app.useGlobalInterceptors(new GlobalInterceptor());
10
app.useGlobalFilters(new GlobalFilter());
11
app.useGlobalGuards(new GlobalGuard());
12
await app.listen(3000);
13
}
14
bootstrap();

With these modifications, the SpecialController in SpecialModule will not be affected by the global interceptors, filters, and guards. Other routes will continue to be processed by the global interceptors, filters, and guards.

Conclusion

By following the above steps, we successfully created a special SpecialModule and added logic to the global interceptors, filters, and guards to bypass the routes of SpecialModule. We hope this article helps you implement this feature in your NestJS project.