Giới thiệu về middleware trong Strapi
Trong Strapi, middleware là các hàm được chèn vào chuỗi xử lý yêu cầu (request pipeline) trước khi tới controller hoặc sau khi trả về response. Khi cần thực hiện các kiểm tra bảo mật, ghi log, hoặc thay đổi dữ liệu đầu vào, middleware là công cụ thích hợp nhất.
Kiến trúc middleware của Strapi v5
Strapi v5 sử dụng kiến trúc plugin, trong đó mỗi middleware được khai báo dưới thư mục src/middlewares. Một middleware phải xuất ra một hàm nhận ctx (context) và next (hàm chuyển sang middleware tiếp theo). Khi next() được gọi, quá trình sẽ tiếp tục; nếu không, middleware có thể trả về response ngay lập tức.
Cấu trúc thư mục
- src/middlewares: chứa các file middleware.
- src/config/middlewares.js: danh sách middleware sẽ được load và thứ tự thực thi.
Ví dụ: Middleware kiểm tra token JWT tùy chỉnh
Giả sử chúng ta muốn tạo một middleware chỉ cho phép các request có header Authorization chứa JWT hợp lệ truy cập vào các route thuộc nhóm /api/private. Các bước thực hiện như sau:
Bước 1: Tạo file middleware
// src/middlewares/jwt-auth.js
module.exports = (config, { strapi }) => {
return async (ctx, next) => {
// Chỉ áp dụng cho đường dẫn bắt đầu bằng /api/private
if (!ctx.request.path.startsWith('/api/private')) {
return await next();
}
const authHeader = ctx.request.header['authorization'];
if (!authHeader) {
ctx.throw(401, 'Missing Authorization header');
}
const token = authHeader.split(' ')[1];
try {
const payload = await strapi.plugins['users-permissions'].services.jwt.verify(token);
// Gắn thông tin người dùng vào ctx.state để các controller dùng tiếp
ctx.state.user = await strapi.query('plugin::users-permissions.user').findOne({ where: { id: payload.id } });
if (!ctx.state.user) {
ctx.throw(401, 'User not found');
}
} catch (err) {
ctx.throw(401, 'Invalid token');
}
await next();
};
};Bước 2: Đăng ký middleware trong cấu hình
Thêm middleware vừa tạo vào danh sách trong src/config/middlewares.js. Thứ tự quan trọng: middleware xác thực phải chạy trước các middleware xử lý body.
// src/config/middlewares.js
module.exports = [
'strapi::errors',
'strapi::security',
// Middleware tùy chỉnh
{ name: 'global::jwt-auth', config: {} },
'strapi::cors',
'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];Bước 3: Kiểm tra hoạt động
Sử dụng công cụ curl hoặc Postman để gửi yêu cầu tới /api/private/articles. Khi không có token hoặc token không hợp lệ, API sẽ trả về lỗi 401. Khi token hợp lệ, request sẽ được chuyển tới controller và trả về dữ liệu bình thường.
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:1337/api/private/articles
Một số lưu ý khi viết middleware
- Không gây chậm trễ: Tránh thực hiện các tác vụ đồng bộ nặng trong middleware; nếu cần, hãy sử dụng async/await.
- Quản lý lỗi: Sử dụng
ctx.throw(status, message)để trả về lỗi chuẩn HTTP, Strapi sẽ tự động format response. - Giữ tính tái sử dụng: Đặt middleware ở mức
globalnếu muốn áp dụng cho toàn bộ API, hoặc khai báo trongapi::.jsđể chỉ áp dụng cho một bộ route. - Kiểm tra quyền (role): Sau khi xác thực, bạn có thể kiểm tra
ctx.state.user.roleđể quyết định cho phép hay từ chối truy cập.
Kết luận
Middleware tùy chỉnh trong Strapi v5 cho phép bạn kiểm soát luồng request một cách linh hoạt, từ việc xác thực JWT, kiểm tra quyền, tới ghi log chi tiết. Khi nắm vững cách tạo và đăng ký middleware, bạn sẽ giảm đáng kể thời gian phát triển các tính năng bảo mật và tuân thủ quy chuẩn API.
Để nắm bắt sâu hơn các kỹ thuật nâng cao và thực hành trên dự án thực tế, Tham khảo khóa học "Xây dựng Back-End Nodejs bằng Strapi CMS" tại đây.








