nestjs之请求的生命周期梳理

发布时间:2024年01月16日

关于请求是如何在 NestJS 应用程序中流经不同的组件和中间件的。以下是关于这些步骤的一些详细解释:

收到请求

请求从客户端到达应用程序。

全局绑定的中间件

全局中间件是在整个应用程序范围内执行的中间件,可以处理请求前和请求后的逻辑,如身份验证和日志记录。

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';

// 创建一个全局中间件
const globalMiddleware = (req, res, next) => {
  // 在这里可以添加全局中间件的逻辑
  console.log('Global Middleware');
  next();
};

@Module({
  controllers: [AppController],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    // 使用全局中间件
    consumer.apply(globalMiddleware).forRoutes('*');
  }
}

模块绑定的中间件

每个模块可以绑定自己的中间件,用于处理与该模块相关的请求。

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { UsersController } from './users.controller';

// 创建一个模块绑定的中间件
const moduleMiddleware = (req, res, next) => {
  // 在这里可以添加模块绑定的中间件的逻辑
  console.log('Module Middleware');
  next();
};

@Module({
  controllers: [UsersController],
})
export class UsersModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    // 使用模块绑定的中间件,将其应用于 UsersController 中的路由
    consumer.apply(moduleMiddleware).forRoutes(UsersController);
  }
}

全局守卫

全局守卫可以用于保护整个应用程序的路由或控制器,以执行某些逻辑,如身份验证或权限检查。

// logging.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class LoggingGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    console.log('Global Guard: Logging request');
    return true;
  }
}

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingGuard } from './logging.guard';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalGuards(new LoggingGuard());
  await app.listen(3000);
}
bootstrap();

控制层守卫

它是针对特定控制器的守卫,可用于执行与该控制器相关的逻辑。
假设我们有一个用于身份验证的守卫。

// auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    // 实现身份验证逻辑
    return true; // 假设认证总是成功
  }
}

在特定的控制器上应用此守卫:

// app.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';

@Controller()
@UseGuards(AuthGuard)
export class AppController {
  @Get()
  getHello(): string {
    return 'Hello World!';
  }
}

路由守卫

路由守卫是特定路由级别的守卫,用于处理与该路由相关的逻辑。
假设我们有一个用于检查用户角色的守卫。

// roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    // 实现角色检查逻辑
    return true; // 假设角色检查总是通过
  }
}

在特定的路由上应用此守卫:

// app.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RolesGuard } from './roles.guard';

@Controller()
export class AppController {
  @Get('admin')
  @UseGuards(RolesGuard)
  getAdminArea(): string {
    return 'Admin Area';
  }
}

全局拦截器(控制器之前)

全局拦截器是在请求到达控制器之前执行的,可以用于处理请求和响应的转换和处理。
全局拦截器会对应用程序中的所有控制器方法起作用。通常在 main.ts 文件中全局设置。

示例:

创建一个简单的日志记录全局拦截器。

// logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    console.log(`[Before Controller] Incoming Request: ${request.method} ${request.url}`);
    return next.handle();
  }
}


在 main.ts 中应用全局拦截器:

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new LoggingInterceptor());
  await app.listen(3000);
}
bootstrap();

控制器层拦截器(控制器之前)

这些拦截器是特定控制器级别的,可以用于在请求到达控制器之前执行一些操作。
控制器层拦截器只会影响应用于特定控制器的所有路由。

示例:

创建一个用于跟踪执行时间的控制器层拦截器。

// execution-time.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class ExecutionTimeInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const start = Date.now();
    return next
      .handle()
  }
}

在特定控制器上应用此拦截器:

// app.controller.ts
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { ExecutionTimeInterceptor } from './execution-time.interceptor';

@Controller()
@UseInterceptors(ExecutionTimeInterceptor)
export class AppController {
  @Get()
  getHello(): string {
    return 'Hello World!';
  }
}

路由拦截器(控制器之前)

路由拦截器是特定路由级别的,用于在请求到达控制器之前执行逻辑。
路由拦截器仅对特定的路由处理器生效。

示例:

创建一个用于检查请求数据的路由拦截器。

// request-check.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class RequestCheckInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Route Interceptor: Checking request...');
    return next.handle();
  }
}

在特定路由上应用此拦截器:

// app.controller.ts
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { RequestCheckInterceptor } from './request-check.interceptor';

@Controller()
export class AppController {
  @Get('special')
  @UseInterceptors(RequestCheckInterceptor)
  getSpecial(): string {
	return 'Special Route!';
  }
}

全局管道

全局管道用于对整个应用程序的输入进行验证和转换,以确保数据的完整性和安全性。
全局管道会应用于应用程序中的所有控制器和路由。

示例:

假设我们有一个简单的日志记录全局管道。

// logging.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';

@Injectable()
export class LoggingPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    console.log('Global Pipe: Logging value', value);
    return value;
  }
}

在 main.ts 中应用全局管道:

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingPipe } from './logging.pipe';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new LoggingPipe());
  await app.listen(3000);
}
bootstrap();

控制器管道

这些管道是特定控制器级别的,用于验证和转换控制器的输入数据。
控制器管道只会影响应用于特定控制器的所有路由。

示例:

创建一个用于数据转换的控制器层管道。

// transform.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';

@Injectable()
export class TransformPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    // 实现数据转换逻辑
    return transformedValue;
  }
}

在特定的控制器上应用此管道:

// app.controller.ts
import { Controller, Get, UsePipes } from '@nestjs/common';
import { TransformPipe } from './transform.pipe';

@Controller()
@UsePipes(TransformPipe)
export class AppController {
  @Get()
  getHello(): string {
    return 'Hello World!';
  }
}

路由管道

路由管道是特定路由级别的,用于验证和转换特定路由的输入数据。
路由管道仅对特定的路由处理器生效。

示例:

创建一个用于验证请求数据的路由管道。

// validation.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';

@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    // 实现验证逻辑
    return validatedValue;
  }
}

在特定路由上应用此管道:

// app.controller.ts
import { Controller, Get, UsePipes } from '@nestjs/common';
import { ValidationPipe } from './validation.pipe';

@Controller()
export class AppController {
  @Get('validate')
  @UsePipes(ValidationPipe)
  validateRoute(): string {
    return 'Validated Route!';
  }
}

路由参数管道

路由参数管道用于验证和转换路由参数。
路由参数管道用于处理和转换特定路由的参数。

示例:

创建一个用于转换路由参数的管道。

// params.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';

@Injectable()
export class ParamsPipe implements PipeTransform {
  transform(value: string, metadata: ArgumentMetadata) {
    // 实现路由参数的转换逻辑
    return parseInt(value, 10);
  }
}

在特定路由参数上应用此管道:

// app.controller.ts
import { Controller, Get, Param, UsePipes } from '@nestjs/common';
import { ParamsPipe } from './params.pipe';

@Controller()
export class AppController {
  @Get('param/:id')
  getParam(@Param('id', ParamsPipe) id: number): string {
	return Parameter: ${id};
  }
}

控制器(方法处理器)

控制器是处理请求的核心组件,它包含处理请求的方法(处理器)。

// app.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { DataService } from './data.service';

@Controller('data')
export class AppController {
  constructor(private readonly dataService: DataService) {}

  @Get()
  getAllData() {
    return this.dataService.getAllData();
  }

  @Post()
  addData(@Body('item') item: string) {
    this.dataService.addData(item);
    return { message: 'Data added successfully!' };
  }
}

服务(如果有)

服务是可选的,用于将业务逻辑从控制器中提取出来,以便更好地组织代码。

// data.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class DataService {
  private data = ['Item1', 'Item2', 'Item3'];

  getAllData() {
    return this.data;
  }

  addData(item: string) {
    this.data.push(item);
  }
}

路由拦截器(请求之后)

路由拦截器是特定路由级别的,用于在请求处理之后执行逻辑。
路由拦截器在特定路由的请求处理完成之后执行。

示例:

创建一个拦截器,用于在特定路由处理完成后执行。

// response-time.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class ResponseTimeInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const start = Date.now();
    return next.handle().pipe(
      tap(() => console.log(`Response time: ${Date.now() - start}ms`)),
    );
  }
}

在控制器中的特定路由上应用该拦截器:

// app.controller.ts
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { ResponseTimeInterceptor } from './response-time.interceptor';

@Controller()
export class AppController {
  @Get('special-route')
  @UseInterceptors(ResponseTimeInterceptor)
  specialRoute() {
    return 'This is a special route';
  }
}

控制器拦截器(请求之后)

控制器拦截器是特定控制器级别的,用于在请求处理之后执行逻辑。
控制器拦截器在控制器的所有路由处理完成后执行。

示例:

创建一个拦截器,用于在控制器级别的所有路由处理完成后执行。

// logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      tap(() => console.log('Logging something after the request is handled')),
    );
  }
}

在特定控制器上应用该拦截器:

// app.controller.ts
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { LoggingInterceptor } from './logging.interceptor';

@Controller()
@UseInterceptors(LoggingInterceptor)
export class AppController {
  @Get()
  getHello(): string {
    return 'Hello World!';
  }
}

全局拦截器(请求之后)

全局拦截器是在请求处理之后执行的,可以处理响应数据的转换和处理。
全局拦截器在应用程序中的所有路由处理完成后执行。

示例:

创建一个全局拦截器,用于在所有路由处理完成后执行。

// audit.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class AuditInterceptor implements NestInterceptor {
 intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
	return next.handle().pipe(
		tap(() => console.log('Audit log for the request')),
	);
  }
}

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AuditInterceptor } from './audit.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new AuditInterceptor());
  await app.listen(3000);
}
bootstrap();

异常过滤器(路由,之后是控制器,之后是全局)

异常过滤器用于捕获和处理应用程序中的异常,可以在路由级别、控制器级别或全局级别设置。

  1. 路由级别的异常过滤器
    路由级别的异常过滤器只会处理与特定路由相关的异常。

示例:

创建一个异常过滤器:

// custom-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';

@Catch()
export class CustomExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception instanceof HttpException
      ? exception.getStatus()
      : HttpStatus.INTERNAL_SERVER_ERROR;

    response.status(status).json({
      statusCode: status,
      message: exception.message,
    });
  }
}

在特定路由上应用该异常过滤器:

// app.controller.ts
import { Controller, Get, UseFilters } from '@nestjs/common';
import { CustomExceptionFilter } from './custom-exception.filter';

@Controller()
export class AppController {
  @Get('specific-route')
  @UseFilters(new CustomExceptionFilter())
  specificRoute() {
    throw new Error('Error in specific route');
  }
}

  1. 控制器级别的异常过滤器
    控制器级别的异常过滤器会处理该控制器内所有路由的异常。

示例:

在控制器上使用 @UseFilters() 装饰器:

// app.controller.ts
import { Controller, Get, UseFilters } from '@nestjs/common';
import { CustomExceptionFilter } from './custom-exception.filter';

@Controller()
@UseFilters(new CustomExceptionFilter())
export class AppController {
  @Get()
  getHello(): string {
    throw new Error('Error in controller');
  }
}

  1. 全局级别的异常过滤器
    全局异常过滤器会应用于应用程序中的所有控制器和路由。

示例:

在 main.ts 中全局注册异常过滤器:

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CustomExceptionFilter } from './custom-exception.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new CustomExceptionFilter());
  await app.listen(3000);
}
bootstrap();

  1. 服务器响应:应用程序生成响应并将其发送回客户端,完成请求-响应周期。
文章来源:https://blog.csdn.net/qq_35094120/article/details/135633416
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。