Giao diện
Cài đặt và sử dụng — Error Handler
Tổng quan
Plugin plugin-error-handler là middleware xử lý lỗi tập trung cho toàn bộ HTTP request pipeline. Mọi exception không được xử lý sẽ bị bắt, phân loại và trả về response lỗi chuẩn hóa cho client.
Yêu cầu
| Thành phần | Yêu cầu |
|---|---|
| Server Digiforce | Phiên bản >= 1.0 |
Quan trọng
Đây là plugin core — không nên tắt. Nhiều plugin khác phụ thuộc vào error handler để đăng ký xử lý lỗi riêng (ví dụ: plugin-departments, plugin-data-source-rest-api).
Bước 1: Xác nhận plugin đã bật
Plugin thường được bật sẵn. Kiểm tra trong Settings → Plugin Manager → tìm plugin-error-handler.
Cơ chế hoạt động
Vị trí trong Middleware Chain
Plugin đăng ký middleware sau i18n và trước cors:
i18n → errorHandler → cors → auth → acl → handlerVị trí này đảm bảo:
- Có thể sử dụng
ctx.i18n.t()để dịch thông báo lỗi (nhờ nằm sau i18n) - Bắt được lỗi từ tất cả middleware downstream (cors, auth, acl, handler)
Luồng xử lý lỗi
Đăng ký handler
Plugin sử dụng pattern guard + render:
typescript
errorHandler.register(
(err) => boolean, // guard: kiểm tra lỗi có thuộc loại này không
(err, ctx) => void // render: xử lý và tạo response
);Khi lỗi xảy ra, plugin duyệt danh sách handler theo thứ tự đăng ký. Handler đầu tiên có guard trả về true sẽ được sử dụng. Nếu không có handler nào khớp, defaultHandler được gọi.
Các loại lỗi được xử lý
1. Sequelize Validation Error
Phát hiện: err.name === 'SequelizeValidationError'
Xử lý:
- Duyệt qua
err.errors(mảng lỗi validation) - Tìm tên trường trong collection schema (
uiSchema.title) - Dịch thông báo lỗi qua i18n
- Trả về HTTP 400
Response:
json
{
"errors": [
{ "message": "Trường 'Email' phải là duy nhất" },
{ "message": "Trường 'Tên' không được để trống" }
]
}2. Unique Constraint Error
Phát hiện: err.name === 'SequelizeUniqueConstraintError'
Xử lý: Tương tự Validation Error — phân tích constraint name để xác định trường bị trùng lặp, dịch thông báo, trả HTTP 400.
3. SQL Syntax Error
Phát hiện theo database:
| Database | Điều kiện |
|---|---|
| MySQL / MariaDB | err.errno === 1064 |
| PostgreSQL | err.code === '42601' |
| SQLite | err.code === 'SQLITE_ERROR' + message chứa "syntax error" |
Xử lý: Trả về thông báo chung "Invalid SQL syntax" (không lộ chi tiết schema). HTTP 500.
4. SQL Reference Error (Invalid Column/Table)
Phát hiện theo database:
| Database | Lỗi | Điều kiện |
|---|---|---|
| MySQL | Unknown column | errno 1054 |
| MySQL | Unknown table | errno 1051, 1146 |
| MySQL | Ambiguous column | errno 1052 |
| PostgreSQL | Unknown column | code '42703' |
| PostgreSQL | Unknown table | code '42P01' |
| PostgreSQL | Ambiguous column | code '42702' |
| SQLite | Unknown column/table | Message pattern matching |
Xử lý: Trả về "Invalid SQL column or table reference". HTTP 400.
5. Lỗi mặc định (Default Handler)
Mọi lỗi không khớp với handler nào sẽ được xử lý bởi defaultHandler:
typescript
ctx.status = err.statusCode || err.status || 500;
ctx.body = {
errors: [{
message: err.message,
code: err.code,
title: err.title, // nếu có
}],
};Nếu lỗi có cause, message sẽ được nối thêm: "message: cause.message".
Đăng ký Custom Error Handler
Các plugin khác có thể đăng ký handler riêng:
typescript
// Ví dụ từ plugin-departments
const errorHandlerPlugin = this.app.pm.get<PluginErrorHandler>('error-handler');
errorHandlerPlugin.errorHandler.register(
(err) => err.message === "Invalid main department...",
(err, ctx) => {
ctx.throw(400, ctx.i18n.t("Invalid main department...", { ns: 'departments' }));
},
);
// Ví dụ từ plugin-data-source-rest-api
errorHandlerPlugin.errorHandler.register(
(err) => err.cause?.errorContent !== undefined,
(err, ctx) => {
ctx.status = 500;
ctx.body = { errors: [{ message: String(err.cause.errorContent) }] };
},
);Response Format chuẩn
Mọi response lỗi tuân theo format:
json
{
"errors": [
{
"message": "Mô tả lỗi",
"code": "MÃ_LỖI",
"title": "Tiêu đề lỗi"
}
]
}| Trường | Bắt buộc | Mô tả |
|---|---|---|
message | Có | Mô tả lỗi (có thể được dịch qua i18n) |
code | Không | Mã lỗi nội bộ |
title | Không | Tiêu đề lỗi |
Logging
Mọi lỗi đều được ghi log trước khi render response:
typescript
ctx.log.error(err.message, {
method: 'error-handler',
err: err.stack,
cause: err.cause,
});Điều này đảm bảo thông tin lỗi đầy đủ (bao gồm stack trace) được lưu trong log system, ngay cả khi client chỉ nhận thông báo chung.
Lưu ý
- Plugin không tạo API endpoint hay database table
- Lỗi 500 chỉ trả thông báo chung cho client — chi tiết nằm trong log server
- Lỗi validation (400) trả về chi tiết trường bị lỗi
- Handler được duyệt theo thứ tự đăng ký — handler đầu tiên khớp sẽ được sử dụng
- Plugin khác nên đăng ký handler trong
beforeLoad()hoặcload()để đảm bảo sẵn sàng