
Chào các "coder nhí" của thầy Creyt! Hôm nay, chúng ta sẽ cùng "flex" kiến thức về một "công cụ" mà dân làm backend Node.js nào cũng phải biết, đó là body-parser. Nghe tên có vẻ "chill phết" nhưng công dụng của nó thì "căng đét" luôn đấy!
body-parser là gì và để làm gì? (Giải thích kiểu Gen Z)
Thế này nhé, các bạn cứ hình dung server Node.js của chúng ta giống như một "anh shipper" siêu cấp "đỉnh của chóp" đang chờ nhận hàng. Khi client (trình duyệt, ứng dụng mobile, Postman...) gửi dữ liệu lên server thông qua các phương thức như POST, PUT, PATCH, thì cái dữ liệu đó nó không tự động "biến hình" thành một object JavaScript mà server có thể đọc được ngay đâu. Nó giống như một gói hàng được đóng gói "kín mít" mà anh shipper phải tự tay bóc ra, xem bên trong là gì, rồi mới biết cách xử lý.
body-parser chính là "nhân viên kiểm tra và phân loại hàng hóa" chuyên nghiệp ở trung tâm vận chuyển của anh shipper. Nhiệm vụ của nó là: bóc tách, đọc nhãn (định dạng dữ liệu như JSON, URL-encoded) và chuyển đổi cái gói hàng "lằng nhằng" đó thành một object JavaScript "sạch sẽ", dễ hiểu" để anh server của chúng ta có thể làm việc ngay mà không cần "đau đầu" suy nghĩ.
Nói cách khác, body-parser giúp server Node.js (cụ thể hơn là Express.js) của bạn "hiểu" được dữ liệu mà client gửi lên trong phần body của HTTP request. Không có nó, bạn sẽ chỉ nhận được một "dòng sông" dữ liệu thô (raw stream of bytes) mà thôi, và việc xử lý nó sẽ "khó nhằn" như chơi game mà không có cheat code vậy!
Code Ví Dụ Minh Hoạ Rõ Ràng, Chuẩn Kiến Thức
Để hiểu rõ hơn, chúng ta cùng "coding" một chút nhé. Đầu tiên, bạn cần khởi tạo project Node.js và cài đặt Express (và body-parser nếu dùng bản cũ) như sau:
npm init -y
npm install express body-parser
1. Server "mù chữ" không có body-parser (để thấy vấn đề):
Nếu không dùng body-parser, khi bạn gửi dữ liệu POST, req.body sẽ là undefined.
// app_without_parser.js
const express = require('express');
const app = express();
const PORT = 3000;
app.use(express.json()); // Dù có cái này nhưng nó chỉ parse JSON. Nếu gửi form URL-encoded vẫn tạch.
app.post('/data', (req, res) => {
console.log('Dữ liệu nhận được (req.body):', req.body);
res.send(`Bạn đã gửi: ${JSON.stringify(req.body)}`);
});
app.listen(PORT, () => {
console.log(`Server chạy trên cổng ${PORT}.`);
console.log('Thử gửi POST request đến http://localhost:3000/data với dữ liệu JSON hoặc form-urlencoded.');
});
Nếu bạn gửi một request POST với Content-Type: application/x-www-form-urlencoded tới /data, req.body sẽ là undefined (trừ khi bạn dùng express.urlencoded()).
2. Sử dụng body-parser để "khai sáng" server:
body-parser cung cấp các middleware khác nhau để xử lý các loại Content-Type khác nhau:
bodyParser.json(): Dùng cho dữ liệu JSON (Content-Type: application/json).bodyParser.urlencoded(): Dùng cho dữ liệu form URL-encoded (Content-Type: application/x-www-form-urlencoded).bodyParser.raw(): Dùng cho dữ liệu nhị phân.bodyParser.text(): Dùng cho dữ liệu văn bản thuần túy.
Chúng ta sẽ tập trung vào json và urlencoded vì chúng phổ biến nhất.
// app_with_parser.js
const express = require('express');
const bodyParser = require('body-parser'); // Import body-parser
const app = express();
const PORT = 3000;
// 1. Sử dụng body-parser cho JSON data
// app.use(bodyParser.json()); // Cách dùng cũ
app.use(express.json()); // Cách dùng mới, được tích hợp sẵn trong Express 4.16.0+
// 2. Sử dụng body-parser cho URL-encoded data
// app.use(bodyParser.urlencoded({ extended: true })); // Cách dùng cũ
app.use(express.urlencoded({ extended: true })); // Cách dùng mới, được tích hợp sẵn trong Express 4.16.0+
// extended: true cho phép parse các object và array lồng nhau
// extended: false chỉ parse string hoặc array đơn giản
app.get('/', (req, res) => {
res.send('Chào mừng đến với server của thầy Creyt!');
});
// Route xử lý dữ liệu JSON
app.post('/api/users', (req, res) => {
const newUser = req.body;
console.log('Dữ liệu người dùng nhận được (JSON):', newUser);
if (newUser && newUser.name && newUser.email) {
res.status(201).json({ message: 'Người dùng đã được tạo thành công!', user: newUser });
} else {
res.status(400).json({ message: 'Dữ liệu không hợp lệ. Cần có tên và email.' });
}
});
// Route xử lý dữ liệu form URL-encoded
app.post('/submit-form', (req, res) => {
const formData = req.body;
console.log('Dữ liệu form nhận được (URL-encoded):', formData);
if (formData && formData.username && formData.password) {
res.status(200).send(`Đăng nhập thành công cho user: ${formData.username}`);
} else {
res.status(400).send('Dữ liệu form không hợp lệ. Cần có username và password.');
}
});
app.listen(PORT, () => {
console.log(`Server chạy trên cổng ${PORT}.`);
console.log('Thử gửi POST request đến http://localhost:3000/api/users (JSON) hoặc http://localhost:3000/submit-form (URL-encoded).');
});
Cách kiểm tra với Postman/Insomnia:
- Để test
/api/users:- Chọn phương thức
POST. - URL:
http://localhost:3000/api/users. - Tab
Body, chọnraw, sau đó chọnJSON(application/json). - Nhập JSON:
{"name": "Creyt", "email": "creyt@example.com", "age": 30}
- Chọn phương thức
- Để test
/submit-form:- Chọn phương thức
POST. - URL:
http://localhost:3000/submit-form. - Tab
Body, chọnx-www-form-urlencoded. - Nhập các cặp key-value:
username: creyt_dev,password: supersecret
- Chọn phương thức
Mẹo (Best Practices) để ghi nhớ hoặc dùng thực tế
-
"Update" kiến thức: Từ phiên bản Express 4.16.0 trở lên, các chức năng của
body-parserđã được tích hợp thẳng vào Express rồi các bạn ạ! Tức là, thay vìrequire('body-parser')rồi dùngbodyParser.json()haybodyParser.urlencoded(), bạn có thể dùng thẳngexpress.json()vàexpress.urlencoded(). Điều này "ngầu" hơn, gọn gàng hơn và là cách hiện đại để làm việc.- Mẹo: Coi
express.json()vàexpress.urlencoded()là phiên bản "upgrade" củabody-parser.
- Mẹo: Coi
-
extended: truehayfalse? Hầu hết các trường hợp, bạn sẽ dùngextended: truevì nó cho phép parse dữ liệu phức tạp hơn như nested objects (object lồng object) hay arrays. Nếu bạn chỉ cần dữ liệu đơn giản (key-value strings),falsecũng được, nhưngtruelà "tiêu chuẩn" hiện tại. -
Đặt đúng chỗ: Luôn
app.use()các middleware parse body trước các route handler mà bạn muốn xử lý dữ liệu. Nếu không, các route handler đó sẽ không thấyreq.bodyđã được parse đâu. -
Giới hạn kích thước payload: Để tránh các cuộc tấn công DoS (Denial of Service) bằng cách gửi dữ liệu quá lớn, bạn nên giới hạn kích thước payload. Cả
express.json()vàexpress.urlencoded()đều có tùy chọnlimit.app.use(express.json({ limit: '10kb' })); // Giới hạn JSON payload tối đa 10KB app.use(express.urlencoded({ extended: true, limit: '10kb' })); // Giới hạn URL-encoded payload tối đa 10KB -
Chỉ dùng khi cần: Nếu một route nào đó của bạn không bao giờ nhận dữ liệu trong body (ví dụ: các route
GET), thì không cần áp dụng middlewarebody-parsercho route đó. Tuy nhiên, việc áp dụng toàn cụcapp.use()là phổ biến và thường không gây vấn đề hiệu suất đáng kể.
Ví dụ thực tế các ứng dụng/website đã ứng dụng
Hầu hết mọi ứng dụng web hoặc API backend sử dụng Node.js và Express đều dùng đến cơ chế tương tự body-parser (dù là body-parser gốc hay express.json()/express.urlencoded()).
- Các API RESTful: Bất kỳ API nào cho phép bạn tạo (POST), cập nhật (PUT/PATCH) tài nguyên (ví dụ: tạo tài khoản người dùng, đăng sản phẩm mới, cập nhật thông tin cá nhân) đều phải đọc dữ liệu từ request body, thường là JSON. Ví dụ: API của Facebook, Instagram, Shopee, Tiki khi bạn đăng nhập, đăng bài, mua hàng...
- Form đăng ký/đăng nhập: Khi bạn điền form đăng ký hoặc đăng nhập trên một website, dữ liệu thường được gửi dưới dạng
application/x-www-form-urlencoded. Server sẽ dùngbody-parser(hoặcexpress.urlencoded()) để đọc username, password và các thông tin khác. - Upload file (với form data): Mặc dù
body-parserkhông trực tiếp xử lý upload file lớn (thường cần các thư viện nhưmulter), nhưng nó vẫn là nền tảng để xử lý các trường văn bản khác trong formmultipart/form-data.
Thử nghiệm đã từng và hướng dẫn nên dùng cho case nào
Thầy Creyt đã từng "combat" với Node.js từ những ngày đầu, khi mà việc parse body request còn "thủ công" bằng cách lắng nghe event data và end trên req stream. Nó "khó nhằn" và "dễ lỗi" lắm! body-parser ra đời như một vị cứu tinh, giúp developer "nhẹ gánh" hơn rất nhiều.
Khi nào nên dùng (hoặc dùng express.json/express.urlencoded):
- Xây dựng API RESTful: Đây là trường hợp phổ biến nhất. Hầu hết các API đều nhận dữ liệu JSON để tạo hoặc cập nhật tài nguyên.
- Xử lý form HTML: Khi bạn có các form
POSTthông thường trên website, dữ liệu sẽ được gửi dưới dạng URL-encoded. - Nhận dữ liệu từ webhook: Nhiều dịch vụ (như Stripe, GitHub, Slack) gửi dữ liệu qua webhook dưới dạng JSON khi có sự kiện xảy ra. Server của bạn cần parse JSON đó.
Tóm lại: Bất cứ khi nào server của bạn cần đọc dữ liệu được gửi trong phần body của một HTTP request (thường là POST, PUT, PATCH), bạn sẽ cần đến "nhân viên phân loại hàng hóa" body-parser (hoặc phiên bản "nâng cấp" express.json()/express.urlencoded()). Nó là một phần không thể thiếu để server của bạn "thông minh" và "khét lẹt" hơn trong việc xử lý dữ liệu client gửi lên đấy!
Thuộc Series: Nodejs
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!