Việc xác thực dữ liệu đầu vào từ phía giao diện người dùng (client) là cực kỳ quan trọng, trong Node.js, có khá nhiều thư viện để làm việc này, có thể bạn đã quen sử dụng Joi hay Yup để xác thực dữ liệu, tuy nhiên, trong bài viết này, mình sẽ giới thiệu và hướng dẫn bạn sử dụng Zod, đây là thư viện xác thực mình sử dụng trong hầu hết các dự án của mình, cùng xem điểm khác biệt của Zod và các thư viện khác nhé
Zod là gì?
Zod là thư viện khai báo và xác thực lược đồ dữ liệu viết bằng TypeScript, được thiết kế thân thiện với lập trình viên và cực kỳ dễ sử dụng.
Zod hoạt động với cả Node và trong trình duyệt, điểm mình thích nhất là không cần phải sử dụng TypeScript mà vẫn tận dụng được các kiểu tĩnh được suy luận ra khi xác thực lược đồ với Zod, ngoài ra rất nhiều tính năng khác, ví dụ tạo Interfaces dựa trên lược đồ đã khai báo cho phía Client, tích hợp với các thư viện quản lý form như React Hook Form, …
Khởi tạo dự án
Cùng thực hành với 1 dự án nhỏ để tìm hiểu về Zod
Tạo thư mục dự án
mkdir zod-example
cd zod-example
Khởi tạo project và cài đặt dependencies
npm init -y
npm i express zod
npm i -D nodemon
Thêm script khởi chạy server
{
// ...
"scripts": {
"start": "nodemon src/server.js"
},
// ...
}
package.json
Tạo server express
Tạo server express đơn giản
const express = require("express");
const app = express().use(express.json());
app.get("/", (req, res, next) => {
return res.status(200).json({
message: "Hello",
});
});
app.listen(3001, () => {
console.log(`Server running at http://localhost:3001/`);
});
src/server.js
Khởi chạy server
npm run dev
Khai báo lược đồ với Zod
Import Zod
const express = require("express");
const { z } = require("zod");
// ...
src/server.js
Khai báo lược đồ, ở đây mình sử dụng một lược đồ đơn giản để xác thực dữ liệu người dùng khi thực hiện đăng nhập
// ...
const loginSchema = z.object({
body: z.object({
username: z.string({
required_error: "Username is required",
}),
password: z
.string({
required_error: "Password is required",
}),
}),
});
// ...
src/server.js
Trong đoạn mã trên:
loginSchema
là object mô tả lược đồ dữ liệu từ requestbody
là object mô tả dữ liệu cần có trongrequest.body
, có thể khai báo dữ liệu với các trường tương tự trongheaders
,query
,params
- Hai trường
username
vàpassword
là 2 chuỗi, với thông báo lỗi tùy chỉnh được cung cấp
Xác thực dữ liệu với lược đồ đã khai báo
Thêm một API để đăng nhập và sử dụng lược đồ loginSchema
đã khai báo ở trên để xác thực dữ liệu trong request
app.post("/users/login", (req, res, next) => {
const { body } = loginSchema.parse(req);
return res.status(200).json({
data
});
})
src/server.js
Ở đây có 2 điểm mình thích:
- Nếu dữ liệu hợp lệ, thì kiểu dữ liệu của
body
sẽ được tự động suy ra từ lược đồ - Nếu dữ liệu không hợp lệ, Zod tự ném ra lỗi, chỉ cần sử dụng 1 hàm bắt lỗi chung để xử lý và trả về thông báo lỗi, hỗ trợ hàm util để định dạng lỗi giúp dễ dàng hiển thị phía giao diện hơn
Thêm global error handler
// ...
app.use((error, req, res, next) => {
if (error instanceof z.ZodError) {
const errors = error.format();
return res.status(400).json(errors);
} else {
return res.status(500).json({
error: "Something wrong :(",
});
}
});
// ...
src/server.js
Và thế là xong, cùng test API thôi, đây là kết quả khi gọi API mà không có dữ liệu trong body
{
"_errors": [],
"body": {
"_errors": [],
"username": {
"_errors": [
"Username is required"
]
},
"password": {
"_errors": [
"Password is required"
]
}
}
}
Còn đây là khi dữ liệu hợp lệ
{
"data": {
"body": {
"username": "banx9x",
"password": "123456"
}
}
}
Tổng kết
Như các bạn thấy, sử dụng Zod giúp thao tác xác thực dữ liệu được tối giản đi khá nhiều, ngoài ra với TypeScript, kiểu dữ liệu được suy luận giúp viết mã dễ dàng và an toàn hơn.
Tất nhiên đây chỉ là một ví dụ đơn giản, còn rất nhiều tính năng thú vị để bạn khám phá nữa, tìm hiểu chi tiết hơn về Zod tại đây. Good luck 🤟!
Bình luận