Một số yêu cầu cần được xử lý trước khi rời khỏi máy của bạn, và một số cần được xử lý ngay khi nhận được phản hồi. Một API thanh toán muốn có chữ ký HMAC được tính toán từ một dấu thời gian và khóa bí mật của bạn. Một điểm cuối đăng nhập trả về một mã thông báo mà mọi cuộc gọi sau đó đều cần. Một quy trình thanh toán phải xác nhận rằng phản hồi thực sự trả về mã 200 và ID đơn hàng chính xác. Bạn có thể tự làm tất cả những điều này, nhưng sẽ rất tốn thời gian và nó sẽ bị hỏng ngay khi bạn chia sẻ yêu cầu với một đồng đội.
Script khắc phục điều đó. Trong Apidog, bạn đính kèm các đoạn JavaScript nhỏ vào một yêu cầu mà chúng sẽ tự động chạy: một bộ trước khi yêu cầu được gửi, một bộ khác sau khi phản hồi quay trở lại. Nếu bạn đã viết script Postman trước đây, thao tác quen thuộc vẫn được giữ nguyên, vì engine của Apidog tương thích với cùng API đối tượng pm. Hướng dẫn này sẽ đi qua cả hai giai đoạn với một ví dụ thực tế: ký một yêu cầu trong script tiền yêu cầu, sau đó trích xuất mã thông báo trong script hậu phản hồi. Hành vi được ghi lại đầy đủ trên tài liệu scripting của Apidog, nhưng tên tab và một vài hành vi khác biệt so với Postman, và những khác biệt đó rất quan trọng.
Script tiền xử lý và hậu xử lý thực sự làm gì
Apidog chạy script theo hai giai đoạn và đặt tên chúng một cách rõ ràng.
Bộ xử lý trước (Pre Processors) chạy trước khi yêu cầu được gửi đến máy chủ. Đây là nơi bạn chuẩn bị mọi thứ: tạo dấu thời gian, tính toán chữ ký, đặt ID đơn hàng ngẫu nhiên hoặc đọc một biến và định hình nó thành một tiêu đề. Phản hồi chưa tồn tại vào thời điểm này, vì vậy bất cứ điều gì kiểm tra phản hồi đều không được phép ở đây.
Bộ xử lý sau (Post Processors) chạy sau khi nhận được phản hồi. Đây là nơi bạn xác minh những gì đã trả về bằng các xác nhận và nơi bạn lấy các giá trị từ phần thân để sử dụng lại sau này. Trích xuất mã thông báo xác thực, lấy ID tài nguyên mới được tạo, kiểm tra mã trạng thái, lưu con trỏ để phân trang.
Hai quy tắc sau đây xuất phát từ sự phân chia đó. Thứ nhất, pm.response (với các thuộc tính code, status, headers, responseTime, responseSize, text(), và json()) chỉ hoạt động trong Bộ xử lý sau. Không có phản hồi nào để đọc trước khi bạn gửi, vì vậy việc gọi nó trong Bộ xử lý trước sẽ không giúp ích gì cho bạn. Thứ hai, các biến là cách hai giai đoạn này giao tiếp với nhau. Bộ xử lý trước thiết lập một giá trị, yêu cầu sử dụng nó và Bộ xử lý sau có thể đọc hoặc ghi đè lên nó.
Nếu bạn chuyển từ Postman, hãy lưu ý sự thay đổi nhãn ngay từ đầu. Các tab của Apidog là Pre Processors và Post Processors, chứ không phải "Pre-request Script" và "Tests". Hành vi tương tự nhau, nhưng tên trên màn hình khác nhau.
Thiết lập: mở một yêu cầu và tìm các tab
Tải xuống Apidog để làm theo. Nó miễn phí và chạy trên macOS, Windows và Linux, vì vậy hãy tải nó từ trang Download Apidog nếu bạn chưa có.
Mở yêu cầu API bạn muốn viết script trong Apidog. Mọi điểm cuối đều có tab Pre Processors và tab Post Processors cùng với các tab Params, Headers và Body thông thường. Để thêm logic vào một trong hai giai đoạn, hãy mở tab và chọn add a Custom Script. Điều đó sẽ mở ra một trình soạn thảo mã nơi bạn viết JavaScript thuần túy dựa trên đối tượng pm.
Trước khi viết bất cứ điều gì, việc biết các giá trị được lưu trữ ở đâu là hữu ích. Apidog giải quyết các biến theo thứ tự ưu tiên này:
Biến cục bộ (Local Variables) > Biến môi trường (Environment Variables) > Biến toàn cục chia sẻ trong dự án (Global Variables Shared within Project) > Biến toàn cục chia sẻ trong nhóm (Global Variables Shared within Team).
Vì vậy, một biến cục bộ sẽ thắng một biến môi trường có cùng tên, và cứ thế theo danh sách. Hãy ghi nhớ điều đó khi một giá trị không như bạn mong đợi: có lẽ có thứ gì đó có độ ưu tiên cao hơn đang che khuất nó. Nếu bạn muốn các giá trị tồn tại qua nhiều yêu cầu, các tham số toàn cục trong Apidog có độ ưu tiên thấp hơn và là nơi tốt để lưu trữ các cài đặt ổn định, trên toàn dự án.
Ví dụ về Bộ xử lý trước: ký một yêu cầu bằng HMAC
Giả sử bạn gọi một điểm cuối thanh toán xác thực mỗi yêu cầu bằng chữ ký HMAC-SHA256. Đây là cùng một mẫu mà nhiều nhà cung cấp sử dụng để xác minh webhook, và tài liệu chữ ký của Stripe mô tả nó rất rõ: máy chủ mong đợi một dấu thời gian và một chữ ký được tính toán trên dấu thời gian đó cộng với phần thân yêu cầu, được mã hóa bằng khóa bí mật API của bạn. Bạn cần tạo cả hai mới mỗi lần gửi.
Apidog đi kèm với crypto-js như một thư viện tích hợp sẵn, vì vậy bạn không cần cài đặt bất cứ thứ gì. Mở tab Pre Processors, chọn add a Custom Script, và viết mã này:
// Pre Processor: ký yêu cầu trước khi nó được gửi
const CryptoJS = require('crypto-js');
// dấu thời gian unix hiện tại tính bằng giây
const timestamp = Math.floor(Date.now() / 1000).toString();
// đọc khóa bí mật từ một biến môi trường
const secret = pm.environment.get('payments_api_secret');
// xây dựng chuỗi để ký: dấu thời gian + xuống dòng + phần thân thô
const body = pm.request.body ? pm.request.body.toString() : '';
const payload = timestamp + '\n' + body;
// tính toán chữ ký HMAC-SHA256, được mã hóa hex
const signature = CryptoJS.HmacSHA256(payload, secret).toString(CryptoJS.enc.Hex);
// lưu trữ cả hai giá trị dưới dạng biến môi trường để yêu cầu sử dụng
pm.environment.set('x_timestamp', timestamp);
pm.environment.set('x_signature', signature);
pm.console.log('Đã ký yêu cầu vào ' + timestamp);
Script đó tính toán chữ ký và lưu cả dấu thời gian và chữ ký vào các biến môi trường. Bây giờ hãy nối chúng vào yêu cầu. Trong tab Headers, tham chiếu các giá trị đã lưu bằng cú pháp {{variableName}}:
X-Timestamp: {{x_timestamp}}
X-Signature: {{x_signature}}
Khi bạn gửi, Apidog chạy Pre Processor trước, đặt hai biến, sau đó thay thế chúng vào các tiêu đề. Máy chủ nhận được một chữ ký hợp lệ tại thời điểm gửi, mọi lúc, không có bước thủ công nào. Lưu ý lệnh gọi require('crypto-js') kéo toàn bộ module. Bạn nhập toàn bộ thư viện, không phải một submodule, vì vậy require('crypto-js') hoạt động và require('crypto-js/sha256') thì không.
Một điều cần lưu ý: các thao tác biến chỉ chạm đến các giá trị hiện tại, không phải các giá trị ban đầu mà bạn có thể đã nhập vào trình soạn thảo môi trường. Đây là điều bạn muốn ở đây, vì chữ ký được cho là ngắn ngủi. Nếu bạn cũng cần giải thích các mẫu ký cho Postman, bài viết về script tiền yêu cầu của Postman cũng bao gồm ý tưởng tương tự với các nhãn của Postman, và nó ánh xạ rõ ràng sang Pre Processors của Apidog.
Ví dụ về Bộ xử lý sau: trích xuất mã thông báo và xác nhận
Bây giờ là giai đoạn khác. Hãy hình dung một yêu cầu đăng nhập trả về một mã thông báo mà bạn cần cho mọi cuộc gọi đã được xác thực sau đó:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": { "id": 4812, "email": "dana@example.com" },
"expires_in": 3600
}
Mở tab Post Processors, chọn add a Custom Script, và kéo mã thông báo ra khỏi phần thân, lưu nó cho các yêu cầu sau này:
// Post Processor: xác minh phản hồi, sau đó trích xuất mã thông báo
pm.test('Trạng thái là 200', function () {
pm.response.to.have.status(200);
});
const jsonData = pm.response.json();
pm.test('Phản hồi trả về một mã thông báo', function () {
pm.expect(jsonData.token).to.be.a('string').and.not.empty;
});
pm.test('ID người dùng có mặt', function () {
pm.expect(jsonData.user.id).to.be.a('number');
});
// lưu trữ mã thông báo để các yêu cầu khác có thể gửi nó
pm.environment.set('auth_token', jsonData.token);
pm.console.log('Đã lưu mã thông báo cho người dùng ' + jsonData.user.email);
Hai điều xảy ra ở đây. Các khối pm.test() xác nhận phản hồi có hình dạng như bạn mong đợi, sử dụng các bộ so khớp pm.expect() kiểu Chai mà Apidog hỗ trợ nguyên bản. Và pm.environment.set('auth_token', jsonData.token) lưu mã thông báo vào môi trường. Bất kỳ yêu cầu nào sau đó giờ đây có thể gửi Authorization: Bearer {{auth_token}} mà bạn không cần phải sao chép thủ công.
Phần xác nhận này đáng được chú ý riêng. Các kiểm tra hậu phản hồi tốt là điều biến một thao tác nhấp và kiểm tra thủ công thành một bài kiểm thử thực sự, và hướng dẫn của chúng tôi về xác nhận API trong Apidog đi sâu hơn vào các bộ so khớp và mẫu đáng biết. Nếu bạn cũng muốn đưa dữ liệu giả thực tế vào các luồng này, Faker.js trong Apidog kết hợp tốt với việc thiết lập biến được hiển thị ở trên.
Một vài hành vi cần giữ thẳng trong Post Processors. pm.iterationData (dữ liệu kiểm thử của bạn) là chỉ đọc, vì vậy bạn có thể đọc một giá trị dựa trên dữ liệu nhưng bạn không thể ghi lại vào nó từ một script. Và pm.cookies trả về cookie từ phản hồi, cookie mà máy chủ đã gửi lại, không phải cookie đã gửi đi cùng yêu cầu của bạn.
Tái sử dụng logic với Script công khai
Sau khi bạn đã viết khối ký HMAC đó, bạn có thể muốn nó trên nhiều yêu cầu hơn. Sao chép-dán nó vào mười điểm cuối có nghĩa là mười nơi cần sửa khi thuật toán thay đổi. Câu trả lời của Apidog là Script công khai (Public Scripts): các đoạn mã tái sử dụng mà bạn viết một lần và đính kèm khi cần.
Tạo một script công khai dưới mục Settings > Public Scripts, sau đó thêm nó vào tab Pre Processors hoặc Post Processors của một yêu cầu. Trong danh sách bộ xử lý, một Public Script và một Custom Script nằm cạnh nhau, và thứ tự rất quan trọng: các script công khai thực thi trước các script tùy chỉnh trong cùng một danh sách, và nếu bạn có nhiều script công khai, chúng sẽ chạy từ trên xuống dưới theo thứ tự đã liệt kê.
Có một vấn đề khiến mọi người vấp ngã. Nếu bạn muốn một Script tùy chỉnh gọi một hàm được định nghĩa trong một Script công khai, hàm đó phải là toàn cục. Một khai báo function thông thường hoặc một hàm được ràng buộc bằng const là cục bộ đối với script của nó và không nhìn thấy được đối với script tiếp theo. Khai báo nó bằng cách gán mà không có var, let, hoặc const:
// Trong Public Script: biến sign() thành toàn cục bằng cách bỏ qua từ khóa
sign = function (payload, secret) {
const CryptoJS = require('crypto-js');
return CryptoJS.HmacSHA256(payload, secret).toString(CryptoJS.enc.Hex);
};
// Trong Custom Script bên dưới nó: gọi hàm toàn cục bằng tên
const timestamp = Math.floor(Date.now() / 1000).toString();
const secret = pm.environment.get('payments_api_secret');
pm.environment.set('x_timestamp', timestamp);
pm.environment.set('x_signature', sign(timestamp, secret));
Thêm Public Script trước, đặt Custom Script bên dưới nó, và lệnh gọi sẽ được giải quyết. Nếu bạn đặt sai thứ tự hoặc thêm const, bạn sẽ gặp lỗi hàm không xác định.
Thư viện, gói bên ngoài và gỡ lỗi
Lệnh nhập crypto-js ở trên là một trong số các thư viện mà Apidog tích hợp sẵn mà không cần thiết lập. Bạn có thể require() bất kỳ thư viện nào trong số chúng trực tiếp:
crypto-js(v3.1.9-1) để băm và HMACjsrsasign(v10.3.0) cho JWT và RSA, yêu cầu Apidog 1.4.5 trở lênchai(v4.2.0) cho các bộ so khớp xác nhậnlodash,moment,uuid,xml2js,cheerio,postman-collection,atob,btoa,csv-parse/lib/sync,tv4,ajv- Các thư viện tích hợp của Node như
path,assert,buffer,util,url,querystring,stream, vàevents
Nếu bạn cần một thứ gì đó không có trong danh sách đó, hãy kéo nó vào lúc chạy bằng $$.liveRequire(), lệnh này sẽ tìm nạp gói ngay lập tức:
$$.liveRequire('nanoid', (nanoid) => {
const id = nanoid.nanoid();
pm.environment.set('request_id', id);
});
Đường dẫn đó cần kết nối internet, vì Apidog tải xuống gói khi script chạy. Các thư viện đi kèm thì không.
Khi một script hoạt động sai, hãy ghi nhật ký để tìm ra lỗi. Cả pm.console.log() và console.log() đều in ra console của Apidog, vì vậy bạn có thể xuất một chữ ký đã tính toán hoặc một trường đã trích xuất và xem chính xác những gì script đã tạo ra trước khi yêu cầu được gửi đi hoặc sau khi nó trả về.
Hai giới hạn nữa đáng nói để chúng không làm bạn ngạc nhiên. pm.sendRequest(), để kích hoạt một lệnh gọi HTTP bổ sung bên trong một script, sử dụng một mẫu callback thay vì Promises, vì vậy hãy viết nó với một callback, không phải await. Và pm.nextRequest() của Postman để nối chuỗi yêu cầu không được hỗ trợ ở đây. Khi bạn cần điều phối quy trình làm việc thực sự, với các bước phân nhánh và điều kiện, Apidog thay vào đó sử dụng Kịch bản kiểm thử (Test Scenarios), nơi bạn sắp xếp các yêu cầu một cách trực quan với các bước Điều kiện và If-Else. Nếu bạn viết script nhiều, Apidog Script Generator tích hợp sẵn cũng có thể tạo bản nháp từ mô tả ngôn ngữ tự nhiên để cung cấp cho bạn một điểm khởi đầu.
Tự động hóa quy trình làm việc với Apidog CLI
Script không chỉ chạy khi bạn nhấp vào nút Gửi. Khi bạn đóng gói các yêu cầu và xác nhận của mình vào một Kịch bản kiểm thử đã lưu, Apidog CLI sẽ chạy toàn bộ kịch bản đó một cách không cần giao diện, bao gồm cả Pre Processors và Post Processors, điều này biến logic ký và trích xuất mã thông báo của bạn thành một phần của CI thay vì một bước thủ công.
Cài đặt CLI và xác thực, sau đó chạy một kịch bản theo id:
npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r cli
Cờ -t là id kịch bản kiểm thử, -e là id môi trường, và -r chọn trình báo cáo (cli, html, hoặc junit, phân tách bằng dấu phẩy cho nhiều trình báo cáo). Tạo mã thông báo truy cập trong cài đặt tài khoản Apidog của bạn, xuất nó dưới dạng APIDOG_ACCESS_TOKEN, và kịch bản tương tự đã chạy trên máy tính để bàn của bạn giờ đây chạy trong CI, bao gồm cả Pre Processors và Post Processors.
Một cảnh báo thành thật: một script dựa vào thứ gì đó chỉ có trên máy của bạn, một tệp cục bộ hoặc một gói bạn đã tải một lần, có thể chạy thành công trong ứng dụng máy tính để bàn nhưng sau đó thất bại trong CLI, bởi vì trình chạy không có sự phụ thuộc đó. Hãy giữ các script trong các thư viện đi kèm hoặc $$.liveRequire() để chúng chạy giống nhau ở mọi nơi.
Câu hỏi thường gặp
Script Apidog có tương thích với các script Postman hiện có của tôi không?
Hầu hết là có. Engine của Apidog sử dụng cùng API đối tượng pm, vì vậy pm.environment.set(), pm.response.json(), pm.test(), và pm.expect() đều hoạt động theo cách bạn đã biết. Hai điểm khác biệt cần nhớ là tên tab, Pre Processors và Post Processors thay vì Pre-request Script và Tests, và một vài lệnh gọi không được hỗ trợ như pm.nextRequest(). Hầu hết các script đều có thể dán và chạy.
Tại sao pm.response trả về undefined trong script tiền yêu cầu của tôi?
Bởi vì chưa có phản hồi nào. Pre Processors chạy trước khi yêu cầu được gửi, vì vậy không có gì được trả về để kiểm tra. Bất kỳ mã nào đọc pm.response (trạng thái, phần thân, tiêu đề của nó) đều thuộc về Post Processor. Nếu bạn cần một giá trị ở giai đoạn trước, hãy lấy nó từ pm.request, một biến hoặc một thư viện thay thế.
Làm cách nào để chia sẻ một script cho nhiều yêu cầu?
Sử dụng Script công khai (Public Scripts) trong Settings > Public Scripts. Viết logic một lần, đính kèm nó vào tab Pre Processors hoặc Post Processors của mỗi yêu cầu và nhớ rằng các script công khai chạy trước các script tùy chỉnh trong cùng một danh sách. Để gọi một hàm Public Script từ một Custom Script, hãy khai báo nó là toàn cục bằng cách gán mà không có var, let hoặc const.
Tôi có thể nhập gói npm mà Apidog không đi kèm không?
Có, với $$.liveRequire('tên-gói', (pkg) => { ... }), sẽ tải xuống gói tại thời điểm chạy và cần kết nối internet. Đối với bất kỳ gói nào trong danh sách tích hợp sẵn, như crypto-js, moment hoặc uuid, hãy sử dụng require() thông thường mà không cần mạng. Lưu ý bạn chỉ có thể yêu cầu toàn bộ module, không phải đường dẫn submodule.
Tôi xem nội dung script của mình đã in ở đâu?
Sử dụng pm.console.log() hoặc console.log() và đọc đầu ra trong console của Apidog sau khi bạn gửi yêu cầu. Đây là cách nhanh nhất để xác nhận một chữ ký đã được tính toán hoặc một mã thông báo đã được trích xuất trước khi bạn tin tưởng nó trong một kịch bản.
Tóm lại
Pre Processors và Post Processors biến một yêu cầu tĩnh thành một yêu cầu tự chuẩn bị và tự kiểm tra công việc của mình. Ký trước khi gửi, trích xuất và xác nhận sau khi nhận, và đưa logic chung vào Public Scripts để bạn chỉ cần viết nó một lần. API pm và các thư viện đi kèm có nghĩa là hầu hết những gì bạn biết từ Postman đều có thể sử dụng trực tiếp. Mở Apidog, chọn bất kỳ yêu cầu nào và thêm Custom Script đầu tiên của bạn để xem cả hai giai đoạn chạy trong một lần gửi duy nhất. Bắt đầu miễn phí, không yêu cầu thẻ tín dụng.
