DEV Community

Cover image for วิธีใช้สคริปต์ Pre-Request และ Post-Response ใน Apidog
Thanawat Wongchai
Thanawat Wongchai

Posted on • Originally published at apidog.com

วิธีใช้สคริปต์ Pre-Request และ Post-Response ใน Apidog

คำขอบางอย่างต้องมีการเตรียมค่าก่อนออกจากเครื่อง และบางอย่างต้องตรวจสอบทันทีหลังได้รับ API response ตัวอย่างเช่น API ชำระเงินอาจต้องใช้ลายเซ็น HMAC จาก timestamp และ secret, endpoint ล็อกอินส่งคืน token สำหรับคำขอถัดไป หรือขั้นตอนชำระเงินต้องตรวจสอบว่า response คืนค่า 200 พร้อมรหัสคำสั่งซื้อที่ถูกต้อง การทำด้วยตนเองซ้ำทุกครั้งทั้งช้าและแชร์ให้ทีมใช้ต่อได้ยาก

ลองใช้ Apidog วันนี้

ใน Apidog คุณสามารถแนบสคริปต์ JavaScript กับคำขอเพื่อให้ทำงานอัตโนมัติได้: ชุดหนึ่งทำงานก่อนส่งคำขอ และอีกชุดทำงานหลังได้รับ response หากเคยใช้ Postman scripts มาก่อน คุณสามารถใช้ pm object API เดิมได้เกือบทั้งหมด บทความนี้จะแสดงวิธีลงนามคำขอด้วย Pre Processor และดึง token ด้วย Post Processor โดยอ้างอิงจาก เอกสารสคริปต์ของ Apidog

สคริปต์ก่อนและหลังทำอะไร

Apidog แบ่งการรันสคริปต์เป็น 2 ขั้นตอน:

  • Pre Processors ทำงานก่อนส่งคำขอ ใช้สำหรับสร้าง timestamp, คำนวณลายเซ็น, กำหนด request ID, หรือแปลงตัวแปรเป็น headers
  • Post Processors ทำงานหลังได้รับ response ใช้สำหรับ assert response, ดึง token, บันทึก resource ID หรือเก็บ cursor สำหรับ pagination

กฎสำคัญมี 2 ข้อ:

  1. pm.response ใช้ได้เฉพาะใน Post Processors เพราะก่อนส่งคำขอยังไม่มี response ให้ตรวจสอบ
  2. ตัวแปรเป็นช่องทางส่งค่าระหว่างขั้นตอน: Pre Processor ตั้งค่า → คำขอใช้ค่า → Post Processor อ่านหรือเขียนทับค่าได้

หากย้ายมาจาก Postman ให้จำชื่อแท็บของ Apidog:

Postman Apidog
Pre-request Script Pre Processors
Tests Post Processors

พฤติกรรมคล้ายกัน แต่ตำแหน่งและชื่อบน UI แตกต่างกัน

การตั้งค่า: เปิดคำขอและเพิ่ม Custom Script

หากยังไม่มีแอป ให้ดาวน์โหลดจากหน้า ดาวน์โหลด Apidog

เปิด API request ที่ต้องการ แล้วเลือกแท็บ Pre Processors หรือ Post Processors ซึ่งอยู่ใกล้กับแท็บ Params, Headers และ Body จากนั้นเลือก add a Custom Script (เพิ่มสคริปต์ที่กำหนดเอง) เพื่อเปิด editor สำหรับเขียน JavaScript ด้วย pm object

ก่อนเริ่มเขียนสคริปต์ ควรเข้าใจลำดับความสำคัญของตัวแปร:

ตัวแปรท้องถิ่น (Local Variables) > ตัวแปรสภาพแวดล้อม (Environment Variables) > ตัวแปรส่วนกลางที่ใช้ร่วมกันในโปรเจกต์ (Global Variables Shared within Project) > ตัวแปรส่วนกลางที่ใช้ร่วมกันในทีม (Global Variables Shared within Team)

หากตัวแปรชื่อเดียวกันมีหลายระดับ ค่าจากระดับที่สูงกว่าจะถูกใช้ก่อน ตัวอย่างเช่น Local Variable จะ override Environment Variable

สำหรับค่าคงที่ระดับโปรเจกต์ เช่น base URL หรือค่า config ร่วม ให้ใช้ พารามิเตอร์ส่วนกลางใน Apidog

ตัวอย่าง Pre Processor: ลงนามคำขอด้วย HMAC

สมมติว่าคุณเรียก API ชำระเงินที่ตรวจสอบทุก request ด้วยลายเซ็น HMAC-SHA256 โดยเซิร์ฟเวอร์ต้องการ:

  • timestamp ปัจจุบัน
  • request body
  • API secret
  • ลายเซ็น HMAC ที่คำนวณจากข้อมูลเหล่านั้น

แนวคิดนี้คล้ายกับรูปแบบในเอกสารลายเซ็นของ Stripe

Apidog มี crypto-js มาให้ในตัว เปิดแท็บ Pre Processors แล้วเพิ่ม Custom Script ดังนี้:

// Pre Processor: ลงนามคำขอก่อนส่ง
const CryptoJS = require('crypto-js');

// timestamp ปัจจุบันในหน่วย Unix seconds
const timestamp = Math.floor(Date.now() / 1000).toString();

// อ่าน secret จาก environment
const secret = pm.environment.get('payments_api_secret');

// สร้าง payload: timestamp + newline + raw body
const body = pm.request.body ? pm.request.body.toString() : '';
const payload = timestamp + '\n' + body;

// คำนวณ HMAC-SHA256 และแปลงเป็น hex
const signature = CryptoJS
  .HmacSHA256(payload, secret)
  .toString(CryptoJS.enc.Hex);

// เก็บค่าให้ request นำไปใช้
pm.environment.set('x_timestamp', timestamp);
pm.environment.set('x_signature', signature);

pm.console.log('ลงนามคำขอเมื่อ ' + timestamp);
Enter fullscreen mode Exit fullscreen mode

จากนั้นเพิ่ม headers ในแท็บ Headers:

X-Timestamp: {{x_timestamp}}
X-Signature: {{x_signature}}
Enter fullscreen mode Exit fullscreen mode

เมื่อกด Send ลำดับการทำงานจะเป็นดังนี้:

  1. Apidog รัน Pre Processor
  2. สคริปต์สร้าง timestamp และ signature
  3. สคริปต์บันทึกค่าลง environment
  4. Apidog แทนที่ {{x_timestamp}} และ {{x_signature}} ใน headers
  5. ส่ง request ที่มีลายเซ็นใหม่ไปยังเซิร์ฟเวอร์

ข้อควรระวัง: ให้ import โมดูลเต็มรูปแบบเท่านั้น

require('crypto-js'); // ใช้ได้
require('crypto-js/sha256'); // ใช้ไม่ได้
Enter fullscreen mode Exit fullscreen mode

การตั้งค่าตัวแปรด้วย pm.environment.set() จะเปลี่ยนเฉพาะ current value ไม่ได้เปลี่ยน initial value ใน environment editor ซึ่งเหมาะกับข้อมูลชั่วคราว เช่น timestamp และ signature

หากต้องการเทียบกับแนวคิดของ Postman ดูเพิ่มเติมได้ที่ สคริปต์ก่อนส่งคำขอของ Postman

ตัวอย่าง Post Processor: ดึง token และยืนยัน response

สมมติว่า login endpoint ส่ง response ดังนี้:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": { "id": 4812, "email": "dana@example.com" },
  "expires_in": 3600
}
Enter fullscreen mode Exit fullscreen mode

เปิดแท็บ Post Processors แล้วเพิ่ม Custom Script:

// Post Processor: ตรวจสอบ response และบันทึก token
pm.test('สถานะคือ 200', function () {
  pm.response.to.have.status(200);
});

const jsonData = pm.response.json();

pm.test('การตอบกลับส่งคืนโทเค็น', function () {
  pm.expect(jsonData.token).to.be.a('string').and.not.empty;
});

pm.test('มี user id อยู่', function () {
  pm.expect(jsonData.user.id).to.be.a('number');
});

// เก็บ token เพื่อใช้กับคำขอถัดไป
pm.environment.set('auth_token', jsonData.token);

pm.console.log('บันทึกโทเค็นสำหรับผู้ใช้ ' + jsonData.user.email);
Enter fullscreen mode Exit fullscreen mode

สคริปต์นี้ทำงาน 2 ส่วน:

  1. pm.test() และ pm.expect() ตรวจสอบว่า response มีสถานะและโครงสร้างที่ถูกต้อง
  2. pm.environment.set('auth_token', jsonData.token) บันทึก token เพื่อนำไปใช้ใน request อื่น

คำขอที่ต้องยืนยันตัวตนสามารถใช้ header นี้ได้ทันที:

Authorization: Bearer {{auth_token}}
Enter fullscreen mode Exit fullscreen mode

การ assert response คือสิ่งที่เปลี่ยนการกด Send แล้วตรวจด้วยตา ให้กลายเป็น API test ที่ทำซ้ำได้ ดูรูปแบบ assertion เพิ่มเติมใน การยืนยัน API ใน Apidog

หากต้องการสร้างข้อมูลทดสอบแบบสมจริง สามารถใช้ Faker.js ใน Apidog ร่วมกับการตั้งค่าตัวแปรได้

ข้อจำกัดที่ควรจำใน Post Processors:

  • pm.iterationData เป็น read-only อ่านข้อมูลทดสอบได้ แต่เขียนค่ากลับไม่ได้
  • pm.cookies คืนค่าคุกกี้ที่มาจาก response ไม่ใช่คุกกี้ที่ส่งออกไปพร้อม request

ใช้ตรรกะซ้ำด้วย Public Scripts

หากมีหลาย endpoint ที่ต้องลงนาม HMAC อย่าคัดลอก Pre Processor เดิมลงทุก request เพราะเมื่ออัลกอริทึมเปลี่ยน คุณจะต้องแก้หลายจุด

ให้สร้าง Public Scripts ที่:

Settings > Public Scripts
Enter fullscreen mode Exit fullscreen mode

จากนั้นแนบ Public Script เข้าไปในแท็บ Pre Processors หรือ Post Processors ของแต่ละ request

ลำดับการทำงานสำคัญ:

  1. Public Scripts ทำงานก่อน
  2. Custom Script ทำงานตามหลัง
  3. หากมี Public Scripts หลายตัว จะทำงานจากบนลงล่าง

หากต้องการให้ Custom Script เรียกฟังก์ชันจาก Public Script ให้ประกาศฟังก์ชันเป็น global โดยไม่ใช้ var, let หรือ const

// Public Script
sign = function (payload, secret) {
  const CryptoJS = require('crypto-js');

  return CryptoJS
    .HmacSHA256(payload, secret)
    .toString(CryptoJS.enc.Hex);
};
Enter fullscreen mode Exit fullscreen mode

จากนั้นเรียกใช้ใน Custom Script ที่อยู่ด้านล่าง:

// Custom Script
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));
Enter fullscreen mode Exit fullscreen mode

หากสลับลำดับสคริปต์ หรือประกาศ sign ด้วย const ฟังก์ชันจะไม่พร้อมใช้งานใน Custom Script และจะเกิดข้อผิดพลาดว่า function is not defined

ไลบรารี, แพ็กเกจภายนอก และการดีบัก

Apidog มีไลบรารีหลายตัวให้ require() ได้โดยตรง:

  • crypto-js (v3.1.9-1) สำหรับ hashing และ HMAC
  • jsrsasign (v10.3.0) สำหรับ JWT และ RSA — ต้องใช้ Apidog 1.4.5 หรือใหม่กว่า
  • chai (v4.2.0) สำหรับ assertion matchers
  • lodash, moment, uuid, xml2js, cheerio, postman-collection
  • atob, btoa, csv-parse/lib/sync, tv4, ajv
  • Node built-ins เช่น path, assert, buffer, util, url, querystring, stream และ events

หากต้องใช้แพ็กเกจที่ไม่มีในรายการ ให้โหลดระหว่าง runtime ด้วย $$.liveRequire():

$$.liveRequire('nanoid', (nanoid) => {
  const id = nanoid.nanoid();

  pm.environment.set('request_id', id);
});
Enter fullscreen mode Exit fullscreen mode

วิธีนี้ต้องเชื่อมต่ออินเทอร์เน็ต เพราะ Apidog จะดาวน์โหลดแพ็กเกจขณะรันสคริปต์ ส่วนไลบรารีที่มีมาในตัวไม่ต้องใช้เครือข่าย

สำหรับการดีบัก ใช้ได้ทั้ง:

pm.console.log('ค่า signature:', signature);
console.log('ค่า token:', jsonData.token);
Enter fullscreen mode Exit fullscreen mode

ดูผลลัพธ์ได้จาก console ของ Apidog หลังส่ง request

ข้อจำกัดเพิ่มเติม:

  • pm.sendRequest() ใช้ callback ไม่ใช่ Promises ดังนั้นอย่าใช้ await
  • pm.nextRequest() ของ Postman ไม่รองรับใน Apidog

หากต้องการ workflow ที่มี branching หรือเงื่อนไข ให้ใช้ Test Scenarios (สถานการณ์การทดสอบ) ซึ่งรองรับขั้นตอน Condition และ If-Else

ทำให้เวิร์กโฟลว์เป็นอัตโนมัติด้วย Apidog CLI

เมื่อรวม requests และ assertions ไว้ใน Test Scenario แล้ว คุณสามารถรัน workflow เดียวกันผ่าน CLI เพื่อใช้ใน CI ได้ โดย Pre Processors และ Post Processors จะทำงานด้วย

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
Enter fullscreen mode Exit fullscreen mode

พารามิเตอร์หลัก:

Flag ความหมาย
-t Test Scenario ID
-e Environment ID
-r Reporter เช่น cli, html, หรือ junit

หากใช้หลาย reporters ให้คั่นด้วยเครื่องหมายคอมมา สร้าง access token จากการตั้งค่าบัญชี Apidog แล้ว export เป็น APIDOG_ACCESS_TOKEN

ข้อควรระวัง: สคริปต์ที่พึ่งพาไฟล์ในเครื่องหรือ dependency ที่มีเฉพาะใน desktop app อาจรันไม่ผ่านใน CLI ให้จำกัดการใช้ไลบรารีที่มาพร้อมเครื่อง หรือใช้ $$.liveRequire() เพื่อให้สคริปต์ทำงานเหมือนกันในทุก environment

คำถามที่พบบ่อย

สคริปต์ Apidog เข้ากันได้กับ Postman scripts หรือไม่?

ส่วนใหญ่ใช่ เพราะใช้ pm object API แบบเดียวกัน เช่น:

pm.environment.set();
pm.response.json();
pm.test();
pm.expect();
Enter fullscreen mode Exit fullscreen mode

ความแตกต่างหลักคือชื่อแท็บ:

  • Apidog ใช้ Pre Processors และ Post Processors
  • Postman ใช้ Pre-request Script และ Tests

นอกจากนี้บาง API เช่น pm.nextRequest() ไม่รองรับ

ทำไม pm.response จึงเป็น undefined ใน Pre Processor?

เพราะ Pre Processor ทำงานก่อนส่ง request จึงยังไม่มี response

โค้ดที่อ่าน status, headers หรือ body ของ response ต้องอยู่ใน Post Processor หากต้องการข้อมูลของ request ใน Pre Processor ให้ดึงจาก pm.request, variables หรือไลบรารีแทน

แชร์สคริปต์เดียวให้หลาย requests ได้อย่างไร?

ใช้ Public Scripts ใน:

Settings > Public Scripts
Enter fullscreen mode Exit fullscreen mode

แนบสคริปต์กับ Pre Processors หรือ Post Processors ของแต่ละ request โดย Public Script จะรันก่อน Custom Script เสมอ

หาก Custom Script ต้องเรียกฟังก์ชันจาก Public Script ให้ประกาศฟังก์ชันเป็น global โดยไม่ใช้ var, let หรือ const

นำเข้า npm package ที่ Apidog ไม่มีมาให้ได้หรือไม่?

ได้ ใช้รูปแบบนี้:

$$.liveRequire('package-name', (pkg) => {
  // ใช้งาน pkg
});
Enter fullscreen mode Exit fullscreen mode

วิธีนี้ต้องใช้อินเทอร์เน็ต สำหรับไลบรารี built-in เช่น crypto-js, moment หรือ uuid ให้ใช้ require() ปกติ

โปรดจำไว้ว่าสามารถ require ได้เฉพาะโมดูลหลัก ไม่ใช่พาธของ submodule

ดู log จากสคริปต์ได้ที่ไหน?

ใช้:

pm.console.log();
console.log();
Enter fullscreen mode Exit fullscreen mode

จากนั้นเปิด console ของ Apidog หลังส่ง request เพื่อดูค่าที่สคริปต์สร้างหรือดึงออกมา

สรุป

Pre Processors และ Post Processors ช่วยให้ API request เตรียมและตรวจสอบตัวเองได้:

  1. ใช้ Pre Processor สำหรับสร้างค่า เช่น timestamp, signature และ request ID
  2. ใช้ Post Processor สำหรับ assert response และบันทึก token หรือ resource ID
  3. ย้ายตรรกะที่ใช้ร่วมกันไปไว้ใน Public Scripts
  4. รัน Test Scenarios ผ่าน CLI เพื่อนำ workflow เดียวกันไปใช้ใน CI

หากคุณใช้ Postman อยู่แล้ว ความรู้เกี่ยวกับ pm API ส่วนใหญ่สามารถนำมาใช้กับ Apidog ได้ทันที เปิด Apidog เลือก request หนึ่งรายการ แล้วเพิ่ม Custom Script แรกเพื่อเริ่มทำให้ API workflow เป็นอัตโนมัติ

Top comments (0)