nestjs统一返回数据格式并添加到swagger文档中

1. 安装swagger依赖包

pnpm i @nestjs/swagger swagger-ui-express

2. 在main.ts添加swagger

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('NestJS API')
    .setDescription('API description')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('doc', app, document);

  await app.listen(3000);
}
bootstrap();

3. 准备统一的返回数据模型

3.1 添加ResponseDto

export class ResponseDto<T = any> {
  @ApiProperty()
  code: number;

  @ApiProperty()
  message: string;

  @ApiProperty({ type: () => Object })
  data: ResponseData<T>;
}

3.2 添加ResponseData

export class ResponseData<T> extends PaginationDto<T> {
  @ApiProperty({ type: () => Object })
  object: T;
}

3.3 添加PaginationDto

export class PaginationDto<T> {
  @ApiProperty()
  total: number;

  @ApiProperty()
  limit: number;

  @ApiProperty()
  offset: number;

  @ApiProperty({ type: () => [Object] })
  list: T[];
}

4. 封装ApiDataResponse装饰器

4.1 当返回单个实体数据

期望data中包含 object 实体数据

ApiDataResponse装饰器代码如下:

export function ApiDataResponse<T>(entity: Type<T>) {
  return applyDecorators(
    ApiExtraModels(ResponseDto, entity),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(ResponseDto) },
          {
            properties: {
              data: {
                properties: {
                  object: { $ref: getSchemaPath(entity) },
                },
              },
            },
          },
        ],
      },
    }),
  );
}

在控制器中使用,返回单个实体数据:

@ApiTags('coffees')
@Controller('coffees')
export class CoffeesController {
  constructor(private readonly coffeesService: CoffeesService) {}

  @ApiDataResponse(Coffee)
  @ApiOperation({ description: '通过ID查询咖啡' })
  @Get(':id')
  async findOne(@Param('id') id: number) {
    const object = await this.coffeesService.findOne(id);
    return { object };
  }
}
4.1.1 接口调用返回的结构

4.1.2 swagger文档的结构

4.2 当返回集合实体数据

期望data中包含 total 总数 limit offset 分页 list 集合数据

ApiDataResponse装饰器代码如下:

export function ApiDataResponse<T>(entity: Type<T>) {
  return applyDecorators(
    ApiExtraModels(ResponseDto, PaginationDto, entity),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(ResponseDto) },
          {
            properties: {
              data: {
                $ref: getSchemaPath(PaginationDto),
                properties: {
                  list: {
                    type: 'array',
                    items: { $ref: getSchemaPath(entity) },
                  },
                },
              },
            },
          },
        ],
      },
    }),
  );
}

在控制器中使用,返回实体集合数据:

@ApiTags('coffees')
@Controller('coffees')
export class CoffeesController {
  constructor(private readonly coffeesService: CoffeesService) {}

  @ApiDataResponse(Coffee)
  @ApiOperation({ description: '获取所有咖啡列表' })
  @Get()
  async findAll(@Query() query: PaginationQueryDto) {
    const list = await this.coffeesService.findAll(query);
    const result = {
      total: list.length,
      limit: query.limit,
      offset: query.offset,
      list: list,
    };
    return result;
  }
}
4.2.1 接口调用返回的结构

4.2.2 swagger文档的结构

4.3 修改ApiDataResponse装饰器

添加 isPaginated 判断是否是集合数据的结构

完整代码如下:

export function ApiDataResponse<T>(entity: Type<T>, isPaginated = false) {
  const dataSchema = isPaginated
    ? {
        $ref: getSchemaPath(PaginationDto),
        properties: {
          list: {
            type: 'array',
            items: { $ref: getSchemaPath(entity) },
          },
        },
      }
    : {
        properties: {
          object: { $ref: getSchemaPath(entity) },
        },
      };

  return applyDecorators(
    ApiExtraModels(ResponseDto, PaginationDto, entity),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(ResponseDto) },
          {
            properties: {
              data: dataSchema,
            },
          },
        ],
      },
    }),
  );
}

在控制器中使用

@ApiTags('coffees')
@Controller('coffees')
export class CoffeesController {
  constructor(private readonly coffeesService: CoffeesService) {}

  @ApiDataResponse(Coffee, true)
  @ApiOperation({ description: '获取所有咖啡列表' })
  @Get()
  async findAll(@Query() query: PaginationQueryDto) {}

  @ApiDataResponse(Coffee)
  @ApiOperation({ description: '通过ID查询咖啡' })
  @Get(':id')
  async findOne(@Param('id') id: number) {}
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Swagger 3. 可以通过在请求头添加 Authorization 字段来统一添加 token。具体操作步骤如下: 1. 在 Swagger UI 找到需要添加 token 的接口,点击右侧的“Authorize”按钮。 2. 在弹出的窗口输入 token,并选择 token 的类型(如 Bearer Token)。 3. 点击“Authorize”按钮,完成 token 的添加。 4. 在请求接口时,Swagger 会自动在请求头添加 Authorization 字段,并将 token 值添加到其。 需要注意的是,每次添加 token 后,Swagger UI 会将 token 保存在浏览器的本地存储,下次访问接口时会自动加载上次保存的 token。如果需要更换 token,可以再次点击“Authorize”按钮,输入新的 token 并保存。 ### 回答2: Swagger3.0是目前市场上使用最为广泛的API文档工具和规范。使用Swagger可以帮助我们更加高效地管理和维护API文档,使得API的开发和调用变得更加方便。在实际的项目,很多API需要使用token来进行身份验证,保障API的安全性。 为了统一添加token,我们需要在Swagger3.0配置文件进行相应的设置。首先,我们需要在Swagger的全局配置添加Authorization header,如下所示: ```yaml swagger: "3.0" info: title: My API version: 1.0.0 description: My API Description servers: - url: http://localhost:8080 description: Local Server security: - bearerAuth: [] components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT ``` 在上述配置,我们使用了OpenAPI 3.0的security配置,其bearerAuth是自定义的名称,我们需要确保这个名称与下面的实际使用一致。在components里面我们定义了securitySchemes,使用JWT作为token传递方式。这样使用者就可以通过在请求header添加Authorization属性来进行token认证了。 接下来,我们需要在API接口的具体定义进行配置。例如,下面展示了一个获取用户信息的API: ```yaml paths: /users/{userId}: get: summary: Get user by ID parameters: - in: path name: userId required: true schema: type: integer format: int64 responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/UserResponse' security: - bearerAuth: [] ``` 在这个示例API,我们添加了security配置并指定了它所属的securitySchemes为bearerAuth。这样我们在访问该API时就必须携带token认证才能成功访问。 总之,通过上述配置我们可以在Swagger3.0统一添加token,保障我们API的安全性。同时,我们也可以在Swagger的UI界面方便的进行API测试和调试。在实际的API开发,我们可以通过结合各种框架和工具,实现更加灵活的API管理和调用。 ### 回答3: Swagger3.0 是一种基于标准 OpenAPI 规范的 API 文档框架,可以快速地生成并描述 REST API 的接口文档,其可读性、可维护性和可测试性都比较高。而对于需要进行用户认证与授权的 API 接口来说,就需要采用一些安全机制以确保 API 请求的合法性。其,token 就是一种常用的认证方式。 在 Swagger3.0 统一添加 token 的方式可以通过以下几步实现: 1.在项目的 pom.xml 文件添加依赖: ```xml <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> ``` 2.在 Swagger3.0 的启动配置文件添加以下代码: ```java @Configuration @EnableSwagger2WebFlux public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .securitySchemes(Arrays.asList(apiKey())) .securityContexts(Arrays.asList(securityContext())); } private ApiKey apiKey() { return new ApiKey("token", "token", "header"); } private SecurityContext securityContext() { return SecurityContext.builder() .securityReferences(Arrays.asList(new SecurityReference("token", new AuthorizationScope[]{}))) .build(); } @Bean public SecurityConfiguration security() { return SecurityConfigurationBuilder.builder() .clientId("test-app-client-id") .clientSecret("test-app-client-secret") .realm("test-app-realm") .appName("test-app") .scopeSeparator(",") .additionalQueryStringParams(null) .useBasicAuthenticationWithAccessCodeGrant(false) .build(); } } ``` 其,ApiKey 主要定义了 token 的名称、位置和类型;SecurityContext 主要定义了针对哪些路径使用 token 认证;SecurityConfiguration 定义了客户端的相关信息和授权方式。 3.在 API 接口添加 @ApiOperation(value = "xxx", authorizations = {@Authorization(value="token")}) 注解,如: ```java @ApiOperation(value = "get user info", authorizations = {@Authorization(value="token")}) @GetMapping("/user/info") public String getUserInfo(HttpServletRequest request) { // 此处添加验证逻辑 return "user info"; } ``` 经过以上配置,Swagger3.0 就会要求在请求头添加名为 token 的参数,并进行认证,才能访问包含 @ApiOperation(value = "xxx", authorizations = {@Authorization(value="token")}) 注解的 API 接口。这样可以提高 API 接口的安全性,阻止未授权的访问,从而保护用户的数据安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值