关于请求是如何在 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();
异常过滤器用于捕获和处理应用程序中的异常,可以在路由级别、控制器级别或全局级别设置。
示例:
创建一个异常过滤器:
// 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');
}
}
示例:
在控制器上使用 @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');
}
}
示例:
在 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();