วันนี้พามาทำตัวจัดการ response เป็นรูปแบบหนึ่งที่ผมใช้งานอยู่ให้เป็นระบบระเบียบ คือการใช้ Interceptor สามารถนำไปใช้งานการเขียนลง log ได้เลย
Response Interceptor คืออะไร?
มีหน้าที่เป็น middleware ที่ทำงานก่อนและหลังการส่ง response ไปยัง client โดยมีหน้าที่หลักคือการจัดรูปแบบ response ให้เป็นมาตรฐานเดียวกัน เช่น การเพิ่มค่าต่างๆ ใน header ของ response หรือการกำหนดรูปแบบข้อมูลที่จะถูกส่งกลับไปยัง client
โค้ดตัวอย่าง
@Injectable()
export class ResponseInterceptor<T>
implements NestInterceptor<T, IStandardResponse<T>> {
constructor(
private readonly cls: ClsService,
) { }
intercept(
context: ExecutionContext,
next: CallHandler,
): Observable<IStandardResponse<T>> {
const now = DateUtil.nowMillis();
const request = context.switchToHttp().getRequest<Request>();
const response = context.switchToHttp().getResponse<Response>();
const reqId =
DateUtil.nowMillis().toString(36) + crypto.randomBytes(6).toString('hex');
const apiReqId = request.headers['request-id'];
response.header('time', String(now));
this.cls.set('reqId', reqId);
this.cls.set('apiReqId', apiReqId);
console.log(response)
return next.handle().pipe(
map((data: T) => {
const responseData = {
resultCode: '20000',
resultDescription: 'Success',
developerMessage: 'Success',
data,
};
return responseData;
}),
);
}
}
รายละเอียดของ ResponseInterceptor
จากโค้ดตัวอย่างนี้ ResponseInterceptor ทำหน้าที่ในการจัดรูปแบบการตอบกลับ (response)
- การตั้งค่าหัวข้อ (Header): เราสามารถเพิ่มข้อมูลลงใน header ของ response ได้ เช่น time หรือ reqId ที่ถูกสร้างขึ้นโดยการใช้เวลาปัจจุบันรวมกับค่าแบบสุ่ม
- การจัดการข้อมูลส่วนกลาง (CLS - Context Local Storage): ใช้ ClsService เพื่อเก็บข้อมูล เช่น reqId และ apiReqId ซึ่งสามารถเรียกใช้ได้ใน service อื่นๆ ที่เกี่ยวข้องภายใน request เดียวกัน
- การจัดรูปแบบ Response: Interceptor จะทำการจัดรูปแบบข้อมูลที่ถูกส่งกลับไปยัง client ให้อยู่ในรูปแบบมาตรฐาน เช่น การระบุ resultCode, resultDescription, และ data เพื่อให้นักพัฒนาสามารถมั่นใจได้ว่ารูปแบบ response จะคงที่และชัดเจนทุกครั้ง
การนำไปใช้งานจริง
การนำ ResponseInterceptor ไปใช้งานสามารถทำได้ง่ายๆ โดยการกำหนดให้เป็น global interceptor ในโมดูลที่ต้องการ เช่น
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: ResponseInterceptor,
},
],
})
export class CommonModule {}
ประโยชน์
- ช่วยให้นักพัฒนาสามารถควบคุมและกำหนดรูปแบบการตอบกลับ API ได้อย่างเป็นมาตรฐาน
- ทำให้ง่ายต่อการติดตามและดีบักในระบบที่มีการร้องขอหลายครั้ง
- ช่วยให้นักพัฒนาสามารถจัดการข้อมูลที่เชื่อมโยงกับการร้องขอหนึ่งๆ ได้อย่างมีประสิทธิภาพ ผ่านการใช้ ClsService
สรุป
ResponseInterceptor ใน NestJS เป็นเครื่องมือที่ช่วยจัดการการตอบกลับ API ให้อยู่ในรูปแบบมาตรฐาน และยังสามารถเพิ่มข้อมูลในส่วนของ header เพื่อติดตามและจัดการข้อมูลใน request ได้อย่างง่ายดาย