Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là QA tại một công ty fintech ở Sài Gòn. Mỗi sáng bạn mở Postman, chạy bộ collection gồm 120 request để kiểm thử API ví điện tử. Nhưng trước khi request đầu tiên bay đi, bạn phải: đăng nhập lấy access token, tính chữ ký HMAC cho payload thanh toán, sinh một mã giao dịch (transaction ID) duy nhất, và gắn timestamp hiện tại. Nếu làm thủ công, bạn mất 5 phút chỉ để chuẩn bị — và chắc chắn sẽ sai ở đâu đó.
Đây chính là lúc Pre-request Script phát huy sức mạnh. Nó là đoạn code JavaScript mà Postman chạy NGAY TRƯỚC khi gửi request đi. Nếu Tests Script (Bài 8) là "kiểm tra sau khi nhận response", thì Pre-request Script là "chuẩn bị đạn dược trước khi bắn". Đây là nơi bạn biến Postman từ một công cụ gõ-tay-gửi-request thành một cỗ máy tự động thông minh.
Trong bài này, chúng ta chỉ tập trung vào phần "trước khi gửi": bạn viết gì ở đó, nó chạy khi nào, và ba nhóm use-case kinh điển mà bất kỳ API tester chuyên nghiệp nào cũng phải nắm — làm mới token, tính toán chữ ký/tham số động, và sinh dữ liệu test. Nắm chắc bài này, bạn sẽ không bao giờ phải copy-paste token bằng tay nữa.
Khái niệm cốt lõi
Pre-request Script là gì và chạy khi nào
Pre-request Script là một tab nằm ngay cạnh tab Body và Tests trong mỗi request Postman. Nó chứa code JavaScript chạy trong môi trường sandbox của Postman (chi tiết về sandbox này là chủ đề của Bài 9). Điểm mấu chốt cần nhớ: đoạn code này thực thi sau khi bạn nhấn Send nhưng trước khi HTTP request thực sự rời khỏi máy tính của bạn.
Vì chạy trước, nó cho phép bạn can thiệp vào request đang chuẩn bị gửi: chèn header, đổi giá trị biến, gắn thêm query param, hoặc thậm chí gọi một API khác để lấy dữ liệu cần thiết trước.
Thứ tự thực thi — điều nhiều người hiểu sai
Postman có nhiều tầng Pre-request Script, và chúng chạy theo thứ tự phân cấp. Khi bạn gửi một request nằm trong một folder, Postman lần lượt chạy:
- Pre-request Script ở cấp Collection
- Pre-request Script ở cấp Folder chứa request
- Pre-request Script ở cấp Request cụ thể
Công cụ chính: pm.variables, pm.environment, pm.request
Trong Pre-request Script, ba đối tượng bạn dùng nhiều nhất là:
pm.environment.set("key", value)— lưu giá trị vào environment hiện tại (ví dụ token vừa lấy).pm.variables.set("key", value)— lưu biến tạm, chỉ sống trong lần chạy hiện tại (thích hợp cho dữ liệu dùng một lần như transaction ID).pm.request— đại diện cho request sắp gửi; bạn có thể đọc/sửa header, body, url của nó.
// Sinh timestamp và lưu vào biến để dùng trong body request
const now = Date.now();
pm.variables.set("requestTime", now);
console.log("Chuẩn bị gửi lúc:", new Date(now).toISOString());
Sau đó trong Body hoặc URL, bạn tham chiếu bằng cú pháp {{requestTime}}. Postman sẽ thay thế biến này ngay trước khi gửi.
pm.sendRequest — vũ khí mạnh nhất của Pre-request
Điều làm Pre-request Script thực sự "nâng cao" là khả năng gọi một request khác trước khi gửi request chính thông qua pm.sendRequest. Đây là hàm bất đồng bộ (asynchronous). Nhờ nó, bạn có thể tự động đăng nhập lấy token, hoặc lấy dữ liệu phụ thuộc, mà không cần thao tác tay. (Các pattern async nâng cao của pm.sendRequest sẽ được đào sâu ở Bài 22; ở đây ta dùng nó cho use-case cơ bản nhưng thiết yếu.)
Tình huống thực tế
Ví dụ 1 — Tự động làm mới access token tại một sàn TMĐT
Bối cảnh: Bạn là QA tại một sàn thương mại điện tử giả định tên ShopViet. API của họ dùng OAuth 2.0, access token hết hạn sau 15 phút. Trước đây, cứ mỗi 15 phút cả team lại phải mở request "Login", copy token từ response, dán vào environment. Một buổi test 3 tiếng nghĩa là làm việc này khoảng 12 lần — vừa mất thời gian vừa dễ dán nhầm.
Giải pháp: Đặt đoạn code sau ở Pre-request Script cấp Collection. Nó kiểm tra token đã hết hạn chưa, nếu rồi thì tự đăng nhập lại:
const tokenExpiry = pm.environment.get("token_expiry");
const now = Date.now();// Nếu chưa có token hoặc đã hết hạn thì lấy token mới
if (!tokenExpiry || now > Number(tokenExpiry)) {
pm.sendRequest({
url: pm.environment.get("base_url") + "/auth/login",
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({
username: pm.environment.get("test_user"),
password: pm.environment.get("test_pass")
})
}
}, function (err, res) {
if (err) {
console.error("Lỗi khi login:", err);
return;
}
const data = res.json();
pm.environment.set("access_token", data.access_token);
// Lưu thời điểm hết hạn: hiện tại + 14 phút (để có biên an toàn)
pm.environment.set("token_expiry", Date.now() + 14 60 1000);
console.log("Đã làm mới access token thành công");
});
}
Sau đó, trong tab Authorization của Collection, bạn dùng token kiểu Bearer với giá trị {{access_token}}.
Bài học rút ra: Đặt logic refresh token ở cấp Collection giúp mọi request trong collection tự động có token hợp lệ. Chú ý mẹo "biên an toàn 14 phút thay vì 15" — để tránh trường hợp token hết hạn đúng lúc request đang bay. Đây là chi tiết nhỏ nhưng cứu bạn khỏi những lỗi 401 khó hiểu.
Ví dụ 2 — Tính chữ ký HMAC cho cổng thanh toán
Bối cảnh: Một startup thanh toán ở Hà Nội, ta gọi là PayNhanh, yêu cầu mỗi request tạo giao dịch phải kèm một chữ ký signature được tính bằng HMAC-SHA256 trên các tham số, với secret key riêng của merchant. Đây là mô hình rất giống VNPay hay MoMo thật (sẽ test cụ thể ở Bài 36–37). Nếu tính chữ ký bằng tay qua công cụ online rồi dán vào, mỗi khi đổi số tiền là bạn phải tính lại — cực kỳ dễ sai.
Giải pháp: Postman có sẵn thư viện crypto-js. Bạn có thể tính chữ ký ngay trong Pre-request Script:
const CryptoJS = require("crypto-js");const amount = 500000; // 500.000 VND
const orderId = "ORD" + Date.now();
const secret = pm.environment.get("merchant_secret");
// Ghép chuỗi dữ liệu theo đúng thứ tự merchant quy định
const rawData = amount=${amount}&orderId=${orderId};
const signature = CryptoJS.HmacSHA256(rawData, secret).toString(CryptoJS.enc.Hex);
pm.variables.set("orderId", orderId);
pm.variables.set("amount", amount);
pm.variables.set("signature", signature);
console.log("Order:", orderId, "| Chữ ký:", signature);
Trong Body request bạn chỉ cần dùng {{orderId}}, {{amount}}, {{signature}}. Mỗi lần Send, chữ ký được tính lại chính xác 100%.
Bài học rút ra: Với API tài chính, thứ tự ghép chuỗi và cách encode phải khớp tuyệt đối với tài liệu của cổng thanh toán. Sai một dấu & hay một khoảng trắng là chữ ký sai và request bị từ chối. Pre-request Script biến việc tính toán dễ sai này thành tự động và tái lập được — đây là lý do QA fintech gần như bắt buộc phải thành thạo nó.
Ví dụ 3 — Sinh dữ liệu test động cho đăng ký tài khoản
Bối cảnh: Team QA của một ứng dụng gọi xe ở Đông Nam Á cần test API đăng ký người dùng mới hàng chục lần mỗi ngày. Vấn đề: email và số điện thoại phải duy nhất, nếu trùng thì API trả về lỗi "đã tồn tại". Gõ tay email mới mỗi lần thì phát mệt.
Giải pháp: Dùng biến động dựng sẵn của Postman kết hợp code tự viết:
// Cách 1: dùng biến động có sẵn của Postman
// {{$randomEmail}}, {{$guid}}, {{$timestamp}} có thể dùng thẳng trong body// Cách 2: tự sinh để kiểm soát định dạng (ví dụ số điện thoại VN)
const suffix = Date.now().toString().slice(-8);
const phone = "09" + suffix; // luôn đúng định dạng VN 10 số
const email = qa_test_${suffix}@vietnamcos.com;
pm.variables.set("newPhone", phone);
pm.variables.set("newEmail", email);
console.log("Tạo user:", email, "-", phone);
Body request dùng {{newEmail}} và {{newPhone}}. Mỗi lần chạy sẽ tạo một user hoàn toàn mới, không bao giờ trùng.
Bài học rút ra: Với dữ liệu cần duy nhất, hãy tận dụng Date.now() hoặc pm.variables.replaceIn('{{$guid}}') làm phần "seed" duy nhất. Đồng thời giữ định dạng hợp lệ (số điện thoại đúng đầu số Việt Nam) để test đúng luồng nghiệp vụ chứ không vướng validation.
Hướng dẫn từng bước
Hãy tự tay dựng một Pre-request Script làm mới token từ đầu:
- Mở request cần chạy trong Postman, chọn tab Pre-request Script (nằm giữa tab Headers/Body và tab Tests).
- Xác định biến cần thiết: Vào environment hiện tại, tạo sẵn các key như
base_url,test_user,test_pass. Đừng hardcode mật khẩu vào script — luôn đọc từ environment.
- Viết logic kiểm tra: Đọc trạng thái hiện tại (ví dụ
token_expiry) bằngpm.environment.get(). Quyết định có cần hành động hay không bằng câu lệnhif.
- Gọi request phụ nếu cần: Dùng
pm.sendRequest(config, callback). Nhớ rằng callback nhận(err, res)— luôn kiểm traerrtrước khi đọcres.
- Lưu kết quả vào biến: Trong callback, dùng
pm.environment.set()cho dữ liệu sống lâu (token) hoặcpm.variables.set()cho dữ liệu dùng một lần.
- Tham chiếu biến trong request chính: Trong URL, Header, hoặc Body, dùng cú pháp
{{tên_biến}}. Postman thay thế chúng ngay trước khi gửi.
- Kiểm tra qua Console: Mở Postman Console (View → Show Postman Console, hoặc Ctrl/Cmd + Alt + C). Nhấn Send và quan sát các dòng
console.logcùng request phụ màpm.sendRequestđã gọi. Đây là cách bạn "nhìn thấy" Pre-request Script đang làm gì.
- Nâng lên cấp Collection: Khi logic đã chạy tốt, cắt code chung (như refresh token) và dán vào Pre-request Script cấp Collection để tái sử dụng cho mọi request.
Lỗi thường gặp & mẹo
Lỗi 1 — Tưởng pm.sendRequest là đồng bộ. Đây là hàm bất đồng bộ. Nếu bạn viết code cần dùng token ngay dòng dưới lệnh pm.sendRequest, nó sẽ chạy trước khi token về. Mọi thao tác phụ thuộc kết quả PHẢI nằm trong callback. Đây là lỗi số một của người mới.
Lỗi 2 — Nhầm phạm vi biến. pm.variables.set() chỉ sống trong lần chạy hiện tại và biến mất sau đó; pm.environment.set() mới lưu bền vào environment. Nếu token của bạn cứ "biến mất" giữa các request, khả năng cao bạn đã dùng nhầm pm.variables thay vì pm.environment. (Chi tiết đầy đủ về các loại biến và scope là chủ đề của Bài 6.)
Lỗi 3 — Refresh token trên mỗi request dù chưa cần. Nếu bỏ điều kiện if kiểm tra hạn, mỗi request sẽ gọi thêm một lần login — collection 120 request thành 240 request, chậm gấp đôi và có thể chạm rate limit. Luôn kiểm tra hạn trước khi refresh.
Lỗi 4 — Hardcode giá trị nhạy cảm. Đừng viết thẳng mật khẩu, secret key vào script. Dùng environment (hoặc Postman Vault — Bài 21) để tách secret ra khỏi code.
Mẹo: Dùng console.log hào phóng khi debug, nhưng nhớ xóa hoặc để mức tối thiểu trước khi chạy trên Newman/CI để log không bị nhiễu. Và khi tính chữ ký, hãy console.log cả chuỗi rawData trước khi hash — hầu hết lỗi chữ ký nằm ở khâu ghép chuỗi, không phải ở hàm hash.
Bài tập thực hành
- Cơ bản: Viết Pre-request Script sinh một
orderIdduy nhất theo định dạngORD+ timestamp, lưu vàopm.variables, và dùng nó trong body của một request POST. Kiểm tra qua Console rằng mỗi lần Send tạo một ID khác nhau.
- Trung cấp: Dựng cơ chế auto-refresh token cho một API công khai bất kỳ có login (ví dụ reqres.in hoặc API nội bộ của bạn). Đặt logic ở cấp Collection, lưu token và thời điểm hết hạn vào environment, và chỉ gọi login lại khi token đã hết hạn.
- Nâng cao: Mô phỏng ví dụ PayNhanh — dùng
crypto-jstính chữ ký HMAC-SHA256 cho một payload gồmamountvàorderId. Đổi số tiền và xác nhận chữ ký thay đổi tương ứng. So sánh kết quả với một công cụ HMAC online để chắc chắn code của bạn đúng.
Tóm tắt
Pre-request Script là đoạn JavaScript chạy ngay trước khi request rời máy bạn, thực thi theo thứ tự Collection → Folder → Request. Ba use-case kinh điển bạn cần thành thạo là: tự động làm mới token (dùng pm.sendRequest + điều kiện kiểm tra hạn), tính tham số động như chữ ký HMAC (dùng crypto-js), và sinh dữ liệu test duy nhất (timestamp, GUID, biến động dựng sẵn). Nhớ ba điều cốt lõi: pm.sendRequest là bất đồng bộ nên dùng callback; phân biệt rõ pm.environment (bền) và pm.variables (tạm); và đặt code dùng chung ở cấp Collection để viết một lần dùng mọi nơi. Khi làm chủ Pre-request Script, bạn đã biến Postman thành một trợ lý tự chuẩn bị mọi thứ trước khi bắn — nền tảng để đi tiếp tới Tests Script và các workflow đa bước ở những bài sau.