260223:1415 20260223 nextJS & nestJS Best pratices
Build and Deploy / deploy (push) Successful in 4m44s
Build and Deploy / deploy (push) Successful in 4m44s
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// File: src/common/exceptions/http-exception.filter.ts
|
||||
// บันทึกการแก้ไข: ปรับปรุง Global Filter ให้จัดการ Error ปลอดภัยสำหรับ Production และ Log ละเอียดใน Dev (T1.1)
|
||||
// Fix #3 & #4: แทน console.error ด้วย Logger, เพิ่ม ErrorResponseBody interface
|
||||
|
||||
import {
|
||||
ExceptionFilter,
|
||||
@@ -11,6 +11,16 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Request, Response } from 'express';
|
||||
|
||||
interface ErrorResponseBody {
|
||||
statusCode: number;
|
||||
timestamp: string;
|
||||
path: string;
|
||||
message?: unknown;
|
||||
error?: string;
|
||||
stack?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
@Catch()
|
||||
export class HttpExceptionFilter implements ExceptionFilter {
|
||||
private readonly logger = new Logger(HttpExceptionFilter.name);
|
||||
@@ -33,49 +43,46 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
||||
: { message: 'Internal server error' };
|
||||
|
||||
// จัดรูปแบบ Error Message ให้เป็น Object เสมอ
|
||||
let errorBody: any =
|
||||
let errorBody: Record<string, unknown> =
|
||||
typeof exceptionResponse === 'string'
|
||||
? { message: exceptionResponse }
|
||||
: exceptionResponse;
|
||||
: (exceptionResponse as Record<string, unknown>);
|
||||
|
||||
// 3. 📝 Logging Strategy (แยกตามความรุนแรง)
|
||||
if (status >= 500) {
|
||||
// 💥 Critical Error: Log stack trace เต็มๆ
|
||||
this.logger.error(
|
||||
`💥 HTTP ${status} Error on ${request.method} ${request.url}`,
|
||||
exception instanceof Error
|
||||
? exception.stack
|
||||
: JSON.stringify(exception),
|
||||
`HTTP ${status} Error on ${request.method} ${request.url}`,
|
||||
exception instanceof Error ? exception.stack : JSON.stringify(exception)
|
||||
);
|
||||
|
||||
// 👇👇 สิ่งที่คุณต้องการ: Log ดิบๆ ให้เห็นชัดใน Docker Console 👇👇
|
||||
console.error('💥 REAL CRITICAL ERROR:', exception);
|
||||
} else {
|
||||
// ⚠️ Client Error (400, 401, 403, 404): Log แค่ Warning พอ ไม่ต้อง Stack Trace
|
||||
this.logger.warn(
|
||||
`⚠️ HTTP ${status} Error on ${request.method} ${request.url}: ${JSON.stringify(errorBody.message || errorBody)}`,
|
||||
`HTTP ${status} Error on ${request.method} ${request.url}: ${JSON.stringify(errorBody['message'] ?? errorBody)}`
|
||||
);
|
||||
}
|
||||
|
||||
// 4. 🔒 Security & Response Formatting
|
||||
// กรณี Production และเป็น Error 500 -> ต้องซ่อนรายละเอียดความผิดพลาดของ Server
|
||||
if (status === 500 && process.env.NODE_ENV === 'production') {
|
||||
if (status === 500 && process.env['NODE_ENV'] === 'production') {
|
||||
errorBody = {
|
||||
message: 'Internal server error',
|
||||
// อาจเพิ่ม reference code เพื่อให้ user แจ้ง support ได้ เช่น code: 'ERR-500'
|
||||
};
|
||||
}
|
||||
|
||||
// 5. Construct Final Response
|
||||
const responseBody = {
|
||||
// 5. Construct Final Response (type-safe)
|
||||
const responseBody: ErrorResponseBody = {
|
||||
statusCode: status,
|
||||
timestamp: new Date().toISOString(),
|
||||
path: request.url,
|
||||
...errorBody, // Spread message, error, validation details
|
||||
...errorBody,
|
||||
};
|
||||
|
||||
// 🛠️ Development Mode: แถม Stack Trace ไปให้ Frontend Debug ง่ายขึ้น
|
||||
if (process.env.NODE_ENV !== 'production' && exception instanceof Error) {
|
||||
if (
|
||||
process.env['NODE_ENV'] !== 'production' &&
|
||||
exception instanceof Error
|
||||
) {
|
||||
responseBody.stack = exception.stack;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user