nestjs入门学习总结(四):实现接口统一格式及请求参数验证

nestjs,入门,学习,总结,实现,接口,统一,格式,请求,参数,验证 · 浏览次数 : 25

小编点评

**接口格式统一请求成功返回** ```typescript { "code": 0, "message": "OK", "data": [] } ``` **接口格式统一请求失败返回** ```typescript { "code": -1, "message": "error reason", "data": null } ``` **使用命令创建一个拦截器** 1. 创建一个新的类,继承 `NestInterceptor`。 2. 在类中实现 `intercept()` 方法,该方法用于拦截请求和响应。 3. 在 `intercept()` 方法中,返回一个 `Observable`,该 Observable 包含响应数据或错误信息。 **示例** ```typescript import { TransformInterceptor } from './transform.interceptor'; @Injectable() export class MyInterceptor implements NestInterceptor { intercept(req: Request, res: Response) { // 处理请求 return res.json({ message: 'Intercepted!' }); } } ``` **使用验证管道** 1. 创建一个管道,该管道用于验证请求参数。 2. 在管道中,使用 `class-validator` 确保参数类型正确。 3. 在控制器中注册管道并使用管道来验证参数。 **注意** * 这些是示例代码,实际代码可能需要根据具体需求进行修改。 * 确保将管道注册到应用程序中。 * 可以根据需要修改错误信息和状态码。

正文

接口格式统一

  • 请求成功返回
{
    "code": 0,
    "message": "OK",
    "data": []
}
  • 请求失败返回
{
    "code": -1,
    "message": "error reason",
    "data": null
}

请求成功返回

这里我们借助拦截器来实现

使用命令创建一个拦截器

nest g interceptor transform
import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Observable, map } from 'rxjs';

/**
 * 拦截器 返回统一响应格式
 */
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map((data) => {
        return {
          data,
          code: 0,
          msg: '请求成功',
        };
      }),
    );
  }
}

handle() 返回一个 Observable。此流包含从路由处理程序返回的值, 因此我们可以使用 map() 运算符轻松地对其进行改变。

全局注册我们刚创建好的拦截器

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { TransformInterceptor } from './core/interceptor/transform.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 全局注册拦截器
  app.useGlobalInterceptors(new TransformInterceptor());
  await app.listen(3000);
}
bootstrap();

请求失败返回

使用命令创建一个异常过滤器

nest g filter http-exception

创建好后,实现HttpExceptionFilter,捕获作为HttpException类实例的异常,并为它们设置自定义响应逻辑。

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
} from '@nestjs/common';

/**
 * 异常过滤器 异常返回统一响应
 * 捕获作为HttpException类实例的异常,并为它们设置自定义响应逻辑
 */
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    // 获取请求上下文
    const ctx = host.switchToHttp();
    // 获取请求上下文中的 response对象
    const response = ctx.getResponse();
    // 获取异常状态码
    const status = exception.getStatus();
    // 异常消息
    const message = exception.message ? exception.message : 'Service Error';
    // Response.json()方法,使用 Response对象直接控制发送的响应。
    response.status(status).json({
      code: -1,
      message: message,
      data: null,
    });
  }
}

全局注册异常过滤器

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './core/filter/http-exception.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 全局注册异常过滤器
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();

抛出异常,在service中使用并抛出异常

import { HttpException, HttpStatus } from '@nestjs/common';

async findAll() {
    throw new HttpException('获取数据失败', HttpStatus.BAD_REQUEST);
}

HttpException 构造函数有两个必要的参数来决定响应:

  • response 参数定义 JSON 响应体。它可以是 string 或 object

  • status参数定义HTTP状态代码。

仅覆盖 JSON 响应主体的消息部分,请在 response参数中提供一个 string。

要覆盖整个 JSON 响应主体,请在response 参数中传递一个object。 Nest将序列化对象,并将其作为JSON 响应返回。

第二个构造函数参数-status-是有效的 HTTP 状态代码。 最佳实践是使用从@nestjs/common导入的 HttpStatus枚举。

以下是几个常见的状态枚举值

HttpStatus.BAD_REQUEST
HttpStatus.FORBIDDEN
HttpStatus.INTERNAL_SERVER_ERROR

为了方便,Nest 提供了一系列继承自核心异常 HttpException 的可用异常

BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableException
InternalServerErrorException
NotImplementedException
BadGatewayException
ServiceUnavailableException
GatewayTimeoutException

HttpStatus和HttpException异常都来自@nestjs/common包中

修改之前的,我们直接使用BadRequestException来抛出异常

// 之前方式
async findAll() {
    throw new HttpException('获取数据失败', HttpStatus.BAD_REQUEST);
}

// 现在方式
async findAll() {
    throw new BadRequestException('获取数据失败');
}

请求参数验证

Nest自带九个开箱即用的管道,他们从 @nestjs/common 包中导出

ValidationPipe
ParseIntPipe
ParseFloatPipe
ParseBoolPipe
ParseArrayPipe
ParseUUIDPipe
ParseEnumPipe
DefaultValuePipe
ParseFilePipe

其中ValidationPipe 配合class-validator就可以完美的实现我们想要的效果(对参数类型进行验证,验证失败抛出异常)。

管道验证操作通常用在dto这种传输层的文件中,用作验证操作。首先我们安装两个需要的依赖包:class-transformer和class-validator

  1. 安装相关库
yarn add class-validator class-transformer
  1. 在dto中添加验证和错误提示信息

更多关于class-validator的用法,可以查看阅读官方文档https://github.com/typestack/class-validator#validation-messages

import { IsString, IsNotEmpty } from 'class-validator';

/**
 * 请求参数验证
 */
export class CreateLinkDto {
  @IsString()
  @IsNotEmpty({ message: '请输入链接名称' })
  readonly name: string;

  @IsString()
  @IsNotEmpty({ message: '请输入链接地址' })
  readonly url: string;
}
  1. 修改异常过滤器,补充增加对object类型情况的判断
import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
} from '@nestjs/common';

/**
 * 异常过滤器 异常返回统一响应
 * 捕获作为HttpException类实例的异常,并为它们设置自定义响应逻辑
 */
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    // 获取请求上下文
    const ctx = host.switchToHttp();
    // 获取请求上下文中的 response对象
    const response = ctx.getResponse();
    // 获取异常状态码
    const status = exception.getStatus();

    let validMessage = '';
    // exceptionResponse返回结果格式: { message: [ '请输入链接名称' ], error: 'Bad Request', statusCode: 400 }
    // exceptionResponse {
    //   message: [ 'name must be a string', '请输入链接名称' ],
    //   error: 'Bad Request',
    //   statusCode: 400
    // }
    const exceptionResponse: any = exception.getResponse();
    // 考虑异常返回object类型的请求
    if (typeof exceptionResponse === 'object') {
      validMessage =
        typeof exceptionResponse.message === 'string'
          ? exceptionResponse.message
          : exceptionResponse.message[0];
    }

    // 异常消息
    const message = exception.message ? exception.message : 'Service Error';
    // Response.json()方法,使用 Response对象直接控制发送的响应。
    response.status(status).json({
      code: -1,
      message: validMessage || message,
      data: null,
    });
  }
}
  1. 注册全局验证管道
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';

import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 全局注册验证管道
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();
  1. 接下来请求接口进行测试
{
    "code": -1,
    "message": "请输入链接名称",
    "data": null
}

{
    "code": -1,
    "message": "name must be a string",
    "data": null
}

项目源码

代码已经上传到github中,欢迎大家star,持续更新,如有任何问题可以联系我v:sky201208(注明来意)

https://github.com/fozero/cloud-collect-nestjs

参考阅读

关于我&前端&node进阶交流学习群

大家好,我是阿健Kerry,一个有趣且乐于分享的人,前小鹏汽车、货拉拉高级前端工程师,长期专注前端开发,如果你对前端&Node.js 学习进阶感兴趣的话(后续有计划也可以),可以关注我,加我微信【sky201208】,拉你进交流群一起交流、学习共同进步,群内氛围特别好,定期会组织技术分享~

与nestjs入门学习总结(四):实现接口统一格式及请求参数验证相似的内容:

nestjs入门学习总结(四):实现接口统一格式及请求参数验证

### 接口格式统一 - 请求成功返回 ``` { "code": 0, "message": "OK", "data": [] } ``` - 请求失败返回 ``` { "code": -1, "message": "error reason", "data": null } ``` #### 请

nestjs入门学习总结(二):中间件、异常过滤器、守卫、管道、拦截器

### 中间件 Nest 中间件可以是一个函数,也可以是一个带有 @Injectable() 装饰器的类,且该类应该实现 NestMiddleware 接口,而函数没有任何特殊要求。 如下是一个日志中间件的简单示例: ``` import { Injectable, NestMiddleware }

nestjs入门学习总结(五):实现用户登录注册功能

### 实现用户注册 1. 我们先使用命令创建两个模块,分别是用户模块和授权模块 ``` nest g resource auth nest g resource user ``` 2. 编写用户实体 ``` import { Entity, Column, PrimaryGeneratedColu

nestjs入门学习总结(三):集成typeorm并实现一个curd操作

### typeorm熟悉 TypeORM 是一个ORM框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,

nestjs入门学习总结(一):控制器、服务、模块

- 为什么要用nestjs,和egg区别对比 - nest项目初始化,了解目录结构 - nest cli命令了解 - nest基础知识点学习:控制器、服务、模块 ### 为什么要用nestjs,和egg区别对比 #### 官网介绍 1. Nest提供了一种开箱即用的应用程序架构,允许开发人员和团队创

next.js app目录 i18n国际化简单实现

最近在用next写一个多语言的项目,找了好久没找到简单实现的教程,实践起来感觉都比较复杂,最后终于是在官方文档找到了,结合网上找到的代码demo,终于实现了,在这里简单总结一下。 此教程适用于比较简单的项目实现,如果你是刚入门next,并且不想用太复杂的方式去实现一个多语言项目,那么这个教程就挺适合

我在前端写Java SpringBoot项目

本篇文章主要是使用 NestJs + Sequelize + MySQL 完成基础运行, 带大家了解 Node 服务端的基础搭建,也可以顺便看看 Java SpringBoot 项目的基础结构,它俩真的非常相似,不信你去问服务端开发同学。