
http.request() trong Node.js: 'Thầy' Creyt Bật Mí Bí Kíp Liên Lạc Server
Chào các bạn Gen Z mê code, hôm nay anh Creyt sẽ cùng các em khám phá một công cụ cực kỳ quyền năng trong Node.js, đó là http.request(). Nghe có vẻ khô khan nhưng tin anh đi, nó là "chìa khóa vàng" để server của chúng ta có thể "nói chuyện" với thế giới bên ngoài đấy!
1. http.request() là gì mà ghê vậy anh Creyt?
Để dễ hình dung nhé, các em cứ nghĩ thế này: Server của chúng ta (ứng dụng Node.js) giống như một "đầu bếp" tài năng trong một nhà hàng. Đầu bếp này không chỉ nấu ăn mà đôi khi còn cần nguyên liệu từ các nhà cung cấp khác (các server/API khác). http.request() chính là cái điện thoại mà đầu bếp dùng để gọi điện đặt hàng nguyên liệu từ những nhà cung cấp đó.
Nói một cách hàn lâm hơn, http.request() là một phương thức cấp thấp (low-level API) trong module http của Node.js, cho phép chúng ta tạo các yêu cầu HTTP (HTTP requests) đến một server từ phía client (trong trường hợp này, client chính là ứng dụng Node.js của chúng ta). Nó cung cấp cho chúng ta toàn quyền kiểm soát từng chi tiết nhỏ nhất của yêu cầu, từ header, method, body cho đến cách xử lý response.
Để làm gì?
Nó sinh ra để giải quyết bài toán giao tiếp giữa các hệ thống. Cụ thể hơn, http.request() giúp chúng ta:
- Lấy dữ liệu từ các API bên ngoài: Ví dụ, server của em cần lấy tỷ giá vàng từ một API tài chính, hay thông tin thời tiết từ một API thời tiết.
- Giao tiếp giữa các microservices: Nếu hệ thống của em được chia thành nhiều dịch vụ nhỏ (microservices),
http.request()là cách để chúng nói chuyện với nhau. - Gửi dữ liệu lên server khác: Ví dụ, em muốn gửi thông báo đến một dịch vụ SMS, hay lưu log vào một hệ thống log tập trung.
- Xây dựng các client HTTP tùy chỉnh: Khi các thư viện cao cấp hơn không đáp ứng được yêu cầu đặc biệt của em.
2. Code Ví Dụ Minh Họa: Từ lý thuyết đến thực chiến
Ok, lý thuyết đủ rồi, giờ mình cùng xắn tay áo vào code một ví dụ cụ thể nhé. Anh sẽ minh họa cả GET và POST.
Đầu tiên, anh em mình sẽ cần một server nhỏ để test. Tạo file mock-server.js:
// mock-server.js
const http = require('http');
const server = http.createServer((req, res) => {
console.log(`[Mock Server] Received ${req.method} request to ${req.url}`);
if (req.url === '/data' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Đây là dữ liệu từ Mock Server!', timestamp: Date.now() }));
} else if (req.url === '/submit' && req.method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString(); // convert Buffer to string
});
req.on('end', () => {
console.log('[Mock Server] POST Body:', body);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'success', receivedData: JSON.parse(body) }));
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Không tìm thấy API này đâu em ơi!');
}
});
server.listen(3000, () => {
console.log('Mock Server đang chạy ở cổng 3000. Sẵn sàng nhận yêu cầu!');
});
Chạy server này lên bằng node mock-server.js.
Bây giờ, tạo file client-request.js để thực hiện yêu cầu:
// client-request.js
const http = require('http');
// --- Ví dụ 1: Gửi GET request để lấy dữ liệu ---
const getOptions = {
hostname: 'localhost',
port: 3000,
path: '/data',
method: 'GET'
};
const getReq = http.request(getOptions, (res) => {
console.log(`\n--- GET Request ---`);
console.log(`Trạng thái: ${res.statusCode}`);
console.log(`Headers: ${JSON.stringify(res.headers)}`);
let data = '';
res.on('data', (chunk) => {
data += chunk; // Thu thập từng phần dữ liệu
});
res.on('end', () => {
try {
const parsedData = JSON.parse(data);
console.log('Dữ liệu nhận được:', parsedData);
} catch (e) {
console.error('Lỗi phân tích JSON:', e);
console.log('Dữ liệu thô:', data);
}
});
});
getReq.on('error', (e) => {
console.error(`Lỗi GET request: ${e.message}`);
});
getReq.end(); // Kết thúc yêu cầu GET (không có body)
// --- Ví dụ 2: Gửi POST request kèm dữ liệu ---
const postData = JSON.stringify({
name: 'Creyt',
age: 25,
hobbies: ['coding', 'teaching', 'coffee']
});
const postOptions = {
hostname: 'localhost',
port: 3000,
path: '/submit',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData) // Quan trọng cho POST!
}
};
const postReq = http.request(postOptions, (res) => {
console.log(`\n--- POST Request ---`);
console.log(`Trạng thái: ${res.statusCode}`);
console.log(`Headers: ${JSON.stringify(res.headers)}`);
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const parsedData = JSON.parse(data);
console.log('Phản hồi từ POST:', parsedData);
} catch (e) {
console.error('Lỗi phân tích JSON:', e);
console.log('Dữ liệu thô:', data);
}
});
});
postReq.on('error', (e) => {
console.error(`Lỗi POST request: ${e.message}`);
});
// Ghi dữ liệu vào body của POST request
postReq.write(postData);
postReq.end(); // Kết thúc yêu cầu POST
Chạy node client-request.js và xem kết quả. Em sẽ thấy server nhận được yêu cầu và trả về dữ liệu đúng như mong đợi.

3. Mẹo Vặt (Best Practices) từ 'Thầy' Creyt
Anh Creyt có vài tips nhỏ để các em dùng http.request() ngon lành cành đào hơn:
- Xử lý lỗi là VÀNG: Mạng không ổn định, server kia sập, hay trả về lỗi 500 là chuyện cơm bữa. Luôn luôn có
req.on('error', ...)để bắt các lỗi network, và kiểm trares.statusCodeđể xử lý lỗi từ server. Đừng bao giờ tin tưởng tuyệt đối vào hệ thống khác, em nhé! res.on('data')vàres.on('end'): Nhớ rằng dữ liệu HTTP response có thể được trả về theo từng "chunk" (từng mảnh nhỏ). Em phải dùngres.on('data')để thu thập tất cả các mảnh đó lại, rồi mới xử lý toàn bộ dữ liệu khi sự kiệnres.on('end')xảy ra.req.end()là bắt buộc: Dù là GET hay POST, em luôn phải gọireq.end()để báo hiệu rằng yêu cầu đã hoàn tất và sẵn sàng gửi đi. Nếu không có nó, request sẽ treo vô thời hạn đó.httpscho an toàn: Nếu server đích dùng HTTPS (có chữscuốihttp), hãy dùngrequire('https')thay vìrequire('http'). Đừng cố gắng dùnghttpđể gọihttpsnhé, nó sẽ không hoạt động đâu và còn nguy hiểm nữa.Content-LengthvàContent-Typecho POST/PUT: Khi gửi dữ liệu trong body (như POST, PUT), luôn đặtContent-Type(ví dụapplication/json) vàContent-Lengthtrong headers.Content-Lengthbáo cho server biết kích thước của dữ liệu sẽ nhận, giúp server chuẩn bị tốt hơn.- Khi nào thì dùng thư viện cao cấp hơn? Thật lòng mà nói,
http.request()rất mạnh nhưng cũng khá "thủ công". Trong phần lớn các dự án thực tế, các em sẽ dùng các thư viện nhưaxioshoặcnode-fetchvì chúng đơn giản hóa việc gửi request, xử lý JSON, và bắt lỗi tốt hơn nhiều. Tuy nhiên, hiểuhttp.request()là nền tảng để các em hiểu các thư viện đó hoạt động như thế nào, và để debug khi cần.
4. Ứng Dụng Thực Tế: Ai đang dùng http.request()?
"Vậy mấy cái app xịn sò có dùng không anh?" Có chứ em! Mặc dù thường được bọc bởi các thư viện cao cấp hơn, nhưng về bản chất, http.request() (hoặc https.request()) vẫn là trái tim của mọi giao tiếp HTTP trong Node.js:
- API Gateway: Một server trung gian nhận request từ client, rồi dùng
http.request()để gọi đến các microservices nội bộ khác để lấy dữ liệu, sau đó tổng hợp lại và trả về cho client. - Webhooks: Khi một sự kiện xảy ra (ví dụ: có đơn hàng mới trên sàn TMĐT), hệ thống sẽ dùng
http.request()để gửi thông báo đến một URL (webhook) mà em đã cấu hình. - Server-Side Rendering (SSR): Khi em dùng Next.js, Nuxt.js, hoặc các framework SSR khác, server của em cần fetch dữ liệu từ API backend trước khi render trang. Đó chính là lúc
http.request()(hoặc các thư viện dựa trên nó) vào việc. - Hệ thống tích hợp: Khi cần kết nối với các hệ thống legacy (hệ thống cũ) hoặc các API có yêu cầu đặc biệt về header, chứng thực mà các thư viện phổ biến không hỗ trợ trực tiếp.
5. Thử Nghiệm của Anh Creyt và Lời Khuyên Nên Dùng Cho Case Nào
Anh Creyt từng có "kỷ niệm" với http.request() khi phải tích hợp với một hệ thống thanh toán của ngân hàng cũ rích. API của họ yêu cầu một kiểu mã hóa body rất đặc biệt và phải gửi một số header tùy chỉnh mà các thư viện thông thường không cho phép tùy biến sâu đến vậy. Lúc đó, http.request() chính là "vị cứu tinh" vì nó cho anh toàn quyền kiểm soát từng byte gửi đi. Anh phải tự tay mã hóa dữ liệu, tính toán Content-Length và đặt các header "lạ đời" đó.
Vậy nên dùng http.request() khi nào?
- Khi em cần kiểm soát tuyệt đối: Nếu em phải làm việc với các API có yêu cầu rất cụ thể về format request, header, hoặc cần tối ưu hiệu suất đến từng milisecond (bằng cách quản lý connection pool thủ công chẳng hạn).
- Khi em đang xây dựng một thư viện HTTP: Nếu em muốn tạo ra một thư viện
fetchhoặcaxioscủa riêng mình (chỉ để học hỏi thôi nhé, đừng làm thật rồi mang vào production!), thìhttp.request()là nền tảng. - Khi debug sâu: Đôi khi, các thư viện cao cấp che giấu quá nhiều chi tiết. Dùng
http.request()giúp em nhìn rõ hơn luồng giao tiếp HTTP, rất hữu ích khi debug các vấn đề mạng phức tạp. - Khi hệ thống của em cực kỳ nhạy cảm về tài nguyên: Mặc dù hiếm, nhưng trong một số trường hợp cực đoan, việc tránh các lớp trừu tượng của thư viện cao cấp có thể giúp tiết kiệm một chút tài nguyên.
Nhưng nhớ nhé, trong hầu hết các trường hợp thông thường, hãy cứ dùng axios hay node-fetch cho nhanh và tiện. http.request() giống như con dao mổ laser vậy, mạnh mẽ nhưng cần người có kinh nghiệm để dùng đúng chỗ. Còn các thư viện kia như dao thái đa năng, làm được nhiều việc mà không cần quá tỉ mỉ.
Hy vọng bài giảng hôm nay của anh Creyt đã giúp các em hiểu rõ hơn về http.request() và biết khi nào nên "triệu hồi" nó ra trận. Chúc các em code vui vẻ!
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é!