ค้นหาเว็บไซต์

javascript - วิธีสร้างการตอบสนองแบบกำหนดเองโดยใช้ globalPipes ใน nestjs


ฉันเขียน API ใน user.controller โดยใช้ DTO ของ 'class-validator'

  @Post('/')
  public async createUser(
    @Res() res,
    @Body() createUserDto: CreateUserDto,
  ) {
    ... do something
  }

และฉันได้ใส่ useGlobalPipes ใน main.ts

  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      transform: true,
      forbidNonWhitelisted: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
  );

เมื่อฉันร้องขอไปยัง API ฉันได้รับการตอบสนองดังด้านล่าง

{
    "statusCode": 400,
    "message": [
        "userName should not be empty",
        "userName must be a string",
    ],
    "error": "Bad Request"
}

จนถึงตอนนี้ มันทำงานได้โดยไม่มีปัญหากับ nestjs
แต่ฉันต้องการรับการตอบสนองแบบกำหนดเองแบบนี้

{
    "code": 400,
    "errorReason": [
        "userName should not be empty",
        "userName must be a string",
    ],
    "msg": "Bad Request",
    "success": false
}

ฉันสามารถรับการตอบกลับแบบกำหนดเองนี้โดยยังคงโค้ดด้านบนได้หรือไม่?
ถ้ามันทำได้ คุณสามารถให้คำแนะนำหรือโค้ดบางส่วนสำหรับสิ่งนี้ได้ไหม?
ขอบคุณที่อ่านคำถามของฉัน

คำตอบ #1

ใน Nest, pipes มีประโยชน์สำหรับการตรวจสอบความถูกต้อง, การเปลี่ยนแปลงวัตถุที่เข้ามา, บางที การติดต่อฐานข้อมูลในบางกรณี, และการโยนข้อผิดพลาดหากมีสิ่งใดผิดพลาด หากคุณต้องการเปลี่ยนการตอบสนองหลังจากที่มีการโยนข้อผิดพลาด, คุณจะต้องพิจารณาการใช้ ExceptionFilter ซึ่งคุณสามารถทำอะไรบางอย่างเหมือนกับ

@Catch()
export class CatchAllFilter implements ExceptionFilter {

  catch(exception: Error, host: ArgumentHost) {
    res
      .status((exception.getStatus && exception.getStatus()) || 500)
      .send({
        (exception.getResponse && ...exception.getResponse()) || ...{ message: exception.message },
        success: false
      });
  }
}

คุณจำเป็นต้องเจอข้อผิดพลาดประเภทกับโค้ดข้างต้น แต่ก็จะนำคุณไปในทิศทางที่ถูกต้อง

คำตอบ #2

มันสายไปนิดหน่อย แต่ถ้าคุณต้องการสร้างการตอบกลับข้อผิดพลาดแบบกำหนดเองใน NestJS คุณต้องเขียน HttpException พร้อม ExceptionFilter

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

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();
    const res: any = exception.getResponse();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      isSuccess: false,
      errror: {
        property: res.property ?? null,
        message: res.message,
      },
    });
  }
}

และจากนั้นนำไปใช้กับ main.ts

app.useGlobalFilters(new HttpExceptionFilter());

ตอนนี้ เรามี HttpExceptionFilter แบบกำหนดเอง และจากนั้นเราต้องสร้างการตอบสนองที่จัดการได้และใช้งานง่าย (สมมติ) สำหรับ frontend

ดังนั้นเราต้องดึงข้อผิดพลาดจาก class validator ที่โยนเข้ามาให้เรา

ใน main.ts

  app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: errors => {
        const result = {
          property: errors[0].property,
          message: Object.values(errors[0].constraints)[0],
        };
        return new BadRequestException(result);
      },
      stopAtFirstError: true,
      whitelist: true,
    })
  );

ที่นี่เราจะคืนค่าข้อผิดพลาดเมื่อทำการตรวจสอบ dto แรกพร้อมคุณสมบัติและข้อความ

และตอนนี้เราจะได้รับการตอบสนองข้อผิดพลาดแบบนี้

{
    "statusCode": 400,
    "timestamp": "2023-12-25T05:18:58.245Z",
    "path": "/gamecategory/create",
    "isSuccess": false,
    "errror": {
        "property": "game_category_name",
        "message": "game_category_name must be a string"
    }
}

หวังว่าสิ่งนี้จะช่วยใครบางคนที่อยากสร้างการตอบสนองข้อผิดพลาดแบบกำหนดเอง และนี่คือคำตอบแรกของฉันใน StackOverflow