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
