กลยุทธ์การกำหนดเวอร์ชัน API ที่ดีที่สุด: URL, Header หรือ Content Negotiation

Ashley Innocent

Ashley Innocent

13 March 2026

กลยุทธ์การกำหนดเวอร์ชัน API ที่ดีที่สุด: URL, Header หรือ Content Negotiation

enterprise.banner.title

enterprise.banner.feature1

enterprise.banner.feature2

enterprise.banner.feature3

enterprise.banner.ctaB

สรุปย่อ

การกำหนดเวอร์ชันด้วย URL (/v1/pets) เป็นกลยุทธ์การกำหนดเวอร์ชัน API ที่ใช้งานได้จริงมากที่สุดสำหรับทีมส่วนใหญ่ สามารถมองเห็นได้, แคชได้ และทดสอบได้ง่าย การกำหนดเวอร์ชันด้วย Header และ Content negotiation มีความเป็น "REST" ที่บริสุทธิ์กว่า แต่เพิ่มความซับซ้อน Modern PetstoreAPI ใช้การกำหนดเวอร์ชันด้วย URL พร้อมกับการกำหนดเวอร์ชันเชิงความหมาย (semantic versioning) และนโยบายการเลิกใช้งานที่ชัดเจน

บทนำ

API ของคุณจำเป็นต้องมีการเปลี่ยนแปลงที่ส่งผลกระทบ (breaking change) คุณกำลังเปลี่ยนรูปแบบการตอบกลับสำหรับ /pets จากอาร์เรย์เปล่าเป็นออบเจกต์ที่มีข้อมูลเมตาสำหรับการแบ่งหน้า (pagination metadata) ไคลเอนต์ที่มีอยู่จะเสียหาย คุณจะทำอย่างไร?

คุณต้องการการกำหนดเวอร์ชัน API แต่จะใช้กลยุทธ์ใด? การกำหนดเวอร์ชันด้วย URL (/v1/pets เทียบกับ /v2/pets)? การกำหนดเวอร์ชันด้วย Header (Accept: application/vnd.petstore.v1+json)? Content negotiation? แต่ละแนวทางมีผู้สนับสนุนที่กระตือรือร้นและความคิดเห็นที่รุนแรง

คำตอบ: การกำหนดเวอร์ชันด้วย URL ชนะใจทีมส่วนใหญ่ เป็นแนวทางที่ใช้งานได้จริง มองเห็นได้ และทำงานร่วมกับเครื่องมือ HTTP ทั้งหมด การกำหนดเวอร์ชันด้วย Header และ Content negotiation นั้นมีความสะอาดในทางทฤษฎีมากกว่า แต่เพิ่มความซับซ้อนที่ทีมส่วนใหญ่ไม่จำเป็นต้องมี

Modern PetstoreAPI ใช้การกำหนดเวอร์ชันด้วย URL พร้อมกับการกำหนดเวอร์ชันเชิงความหมาย และนโยบายการเลิกใช้งานที่ชัดเจน เวอร์ชันปัจจุบันคือ v1 โดยมี v2 ที่วางแผนไว้สำหรับการเปลี่ยนแปลงที่ส่งผลกระทบในอนาคต

💡
หากคุณกำลังสร้างหรือทดสอบ REST API, Apidog ช่วยให้คุณทดสอบ API หลายเวอร์ชัน, ตรวจสอบพฤติกรรมเฉพาะเวอร์ชัน และรับรองความเข้ากันได้ย้อนหลัง คุณสามารถดูแลรักษาข้อมูลจำเพาะแยกกันสำหรับแต่ละเวอร์ชันและรันการทดสอบกับทุกเวอร์ชันพร้อมกันได้
button

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

ทำไม API จึงต้องการการกำหนดเวอร์ชัน

API มีการพัฒนา คุณเพิ่มคุณสมบัติ แก้ไขข้อผิดพลาด และปรับปรุงการออกแบบ บางครั้งการเปลี่ยนแปลงเหล่านี้ทำให้ไคลเอนต์ที่มีอยู่เสียหาย

การเปลี่ยนแปลงที่ส่งผลกระทบ (Breaking Changes)

การเปลี่ยนแปลงที่ทำให้ไคลเอนต์ที่มีอยู่เสียหาย:

1. การลบฟิลด์:

// v1
{"id": "123", "name": "Fluffy", "age": 3}

// v2 (เสียหาย: ลบ age ออกไป)
{"id": "123", "name": "Fluffy"}

2. การเปลี่ยนประเภทฟิลด์:

// v1
{"price": "19.99"}

// v2 (เสียหาย: string เป็น number)
{"price": 19.99}

3. การเปลี่ยนโครงสร้างการตอบกลับ:

// v1 (อาร์เรย์เปล่า)
[{"id": "123"}]

// v2 (เสียหาย: ออบเจกต์ที่ถูกห่อหุ้ม)
{"data": [{"id": "123"}], "pagination": {...}}

4. การเปลี่ยนโครงสร้าง URL:

// v1
GET /pet/123

// v2 (เสียหาย: รูปพหูพจน์)
GET /pets/123

5. การเปลี่ยนการยืนยันตัวตน:

// v1: API key ใน query
GET /pets?api_key=xxx

// v2 (เสียหาย: Bearer token)
GET /pets
Authorization: Bearer xxx

การเปลี่ยนแปลงที่ไม่ส่งผลกระทบ (Non-Breaking Changes)

การเปลี่ยนแปลงที่ไม่ทำให้ไคลเอนต์เสียหาย:

การตัดสินใจเรื่องการกำหนดเวอร์ชัน

เมื่อคุณต้องการการเปลี่ยนแปลงที่ส่งผลกระทบ คุณมีสองทางเลือก:

1. บังคับให้ไคลเอนต์ทั้งหมดอัปเกรด - ง่าย แต่ทำให้การรวมระบบที่มีอยู่เสียหาย

2. รองรับหลายเวอร์ชัน - ใช้ความพยายามมากขึ้น แต่รักษาความเข้ากันได้ย้อนหลัง

API สาธารณะส่วนใหญ่เลือกตัวเลือกที่ 2 การกำหนดเวอร์ชันช่วยให้คุณพัฒนา API ได้ในขณะที่ให้เวลาไคลเอนต์ในการโยกย้าย

การกำหนดเวอร์ชันด้วย URL

การกำหนดเวอร์ชันด้วย URL คือการใส่หมายเลขเวอร์ชันในพาธของ URL

วิธีการทำงาน

GET /v1/pets
GET /v2/pets

เวอร์ชันเป็นส่วนหนึ่งของตัวระบุทรัพยากร เวอร์ชันที่แตกต่างกันคือทรัพยากรที่แตกต่างกัน

ข้อดี

1. มองเห็นได้ชัดเจน

เวอร์ชันอยู่ใน URL คุณสามารถเห็นได้ในบันทึก (logs), ประวัติเบราว์เซอร์ และเอกสารประกอบ ไม่ต้องจำ Header ที่ซ่อนอยู่

2. ทดสอบง่าย

curl https://petstoreapi.com/v1/pets
curl https://petstoreapi.com/v2/pets

คุณสามารถทดสอบทั้งสองเวอร์ชันด้วยการร้องขอ HTTP ง่ายๆ

3. ทำงานร่วมกับเครื่องมือ HTTP ทั้งหมด

เบราว์เซอร์, แคช, พร็อกซี และโหลดบาลานเซอร์มองเห็น URL ที่แตกต่างกัน พวกเขาสามารถกำหนดเส้นทาง, แคช และบันทึกแต่ละเวอร์ชันได้อย่างอิสระ

4. ง่ายสำหรับไคลเอนต์

ไคลเอนต์เพียงแค่เปลี่ยน URL ไม่ต้องมี Header แบบกำหนดเองหรือตรรกะ Content negotiation

5. เลิกใช้งานง่าย

คุณสามารถลบ Endpoints /v1 ได้โดยไม่ส่งผลกระทบต่อ /v2

ข้อเสีย

1. ไม่ "REST" ที่บริสุทธิ์

ผู้เคร่ง REST จะโต้แย้งว่า /v1/pets/123 และ /v2/pets/123 เป็นทรัพยากรเดียวกัน ดังนั้นควรมี URL เดียวกัน เวอร์ชันควรอยู่ใน Header หรือ Content negotiation

2. URL ไม่สะอาดตา

API ของคุณมี URL หลายชุด: /v1/*, /v2/* เป็นต้น

3. ยากต่อการกำหนดเวอร์ชันทรัพยากรแต่ละรายการ

หากคุณต้องการกำหนดเวอร์ชันเพียงแค่ Endpoint เดียว คุณจะต้องกำหนดเวอร์ชัน API ทั้งหมด หรือสร้างความไม่สอดคล้องกัน

การใช้งาน

เวอร์ชันหลักใน URL:

/v1/pets
/v2/pets

ไม่ต้องรวมเวอร์ชันรอง:

❌ /v1.2/pets  (ละเอียดเกินไป)
✅ /v1/pets    (เฉพาะเวอร์ชันหลัก)

ใช้การกำหนดเวอร์ชันเชิงความหมายภายใน:

Modern PetstoreAPI ใช้การกำหนดเวอร์ชันด้วย URL โดยมี /v1 เป็นเวอร์ชันปัจจุบัน

การกำหนดเวอร์ชันด้วย Header

การกำหนดเวอร์ชันด้วย Header คือการใส่เวอร์ชันใน HTTP Header แบบกำหนดเอง

วิธีการทำงาน

GET /pets
API-Version: 1

GET /pets
API-Version: 2

URL ยังคงเหมือนเดิม Header ระบุเวอร์ชัน

ข้อดี

1. URL ที่สะอาดตา

/pets เหมือนกันสำหรับทุกเวอร์ชัน ไม่มีคำนำหน้า /v1 หรือ /v2

2. มีความเป็น "RESTful" มากกว่า

ตัวระบุทรัพยากร (/pets/123) ไม่เปลี่ยนแปลง การนำเสนอเปลี่ยนไปตาม Header

3. การกำหนดเวอร์ชันที่ละเอียด

คุณสามารถกำหนดเวอร์ชันทรัพยากรแต่ละรายการได้:

GET /pets
API-Version: 2

GET /orders
API-Version: 1

ข้อเสีย

1. มองไม่เห็น

เวอร์ชันไม่ได้อยู่ใน URL คุณไม่สามารถเห็นได้ในบันทึกหรือประวัติเบราว์เซอร์โดยไม่ต้องตรวจสอบ Header

2. ทดสอบยากขึ้น

curl -H "API-Version: 1" https://petstoreapi.com/pets
curl -H "API-Version: 2" https://petstoreapi.com/pets

คุณต้องจำไว้ว่าต้องรวม Header เข้าไปด้วย

3. ความซับซ้อนของการแคช

แคชต้องพิจารณา Header API-Version คุณต้องมี Vary: API-Version ในการตอบกลับ

4. ความซับซ้อนของไคลเอนต์

ไคลเอนต์ต้องการตรรกะ Header แบบกำหนดเอง ไคลเอนต์ HTTP บางตัวก็ไม่ได้ทำให้สิ่งนี้ง่าย

5. ความคลุมเครือของเวอร์ชันเริ่มต้น

จะเกิดอะไรขึ้นถ้าไคลเอนต์ไม่ได้ส่ง Header? คุณต้องมีค่าเริ่มต้น ซึ่งสร้างพฤติกรรมที่ไม่ชัดเจน

การใช้งาน

Header แบบกำหนดเอง:

API-Version: 1

หรือใช้ Header Accept:

Accept: application/vnd.petstore.v1+json

รวม Header Vary:

Vary: API-Version

นี่เป็นการบอกแคชให้พิจารณา Header เมื่อทำการแคช

Content Negotiation

Content negotiation ใช้ Header Accept ร่วมกับ Media type แบบกำหนดเอง

วิธีการทำงาน

GET /pets
Accept: application/vnd.petstore.v1+json

GET /pets
Accept: application/vnd.petstore.v2+json

เวอร์ชันเป็นส่วนหนึ่งของ Media type

ข้อดี

1. "RESTful" ที่สุด

นี่คือวิธีการออกแบบ REST การนำเสนอที่แตกต่างกันของทรัพยากรเดียวกัน

2. เป็นไปตามมาตรฐาน HTTP

ใช้ Content negotiation มาตรฐานของ HTTP

3. รองรับหลายรูปแบบ

คุณสามารถกำหนดเวอร์ชันและรูปแบบพร้อมกันได้:

Accept: application/vnd.petstore.v1+json
Accept: application/vnd.petstore.v1+xml

ข้อเสีย

1. ซับซ้อน

ไคลเอนต์ต้องเข้าใจ Media type และ Content negotiation

2. ทดสอบยากขึ้น

curl -H "Accept: application/vnd.petstore.v1+json" https://petstoreapi.com/pets

3. การสนับสนุนเครื่องมือที่ไม่ดี

ไคลเอนต์ HTTP และเครื่องมือจำนวนมากจัดการ Media type แบบกำหนดเองได้ไม่ดี

4. ความซับซ้อนของการแคช

แคชต้องพิจารณา Header Accept คุณต้องมี Vary: Accept

5. เกินความจำเป็นสำหรับ API ส่วนใหญ่

API ส่วนใหญ่ไม่ต้องการความซับซ้อนระดับนี้

การใช้งาน

Media type เฉพาะผู้ขาย:

Accept: application/vnd.petstore.v1+json

การตอบกลับ:

Content-Type: application/vnd.petstore.v1+json
Vary: Accept

Modern PetstoreAPI ใช้งานการกำหนดเวอร์ชันอย่างไร

Modern PetstoreAPI ใช้การกำหนดเวอร์ชันด้วย URL พร้อมนโยบายที่ชัดเจน

เวอร์ชันปัจจุบัน: v1

https://petstoreapi.com/v1/pets
https://petstoreapi.com/v1/orders
https://petstoreapi.com/v1/users

Endpoints ทั้งหมดอยู่ภายใต้ /v1

Header การตอบกลับเวอร์ชัน

การตอบกลับทุกรายการจะรวมเวอร์ชัน API:

X-API-Version: 1.2.0

สิ่งนี้แสดงเวอร์ชันที่ถูกต้อง (major.minor.patch) แม้ว่า URL จะแสดงเฉพาะเวอร์ชันหลักเท่านั้น

คำเตือนการเลิกใช้งาน

เมื่อเวอร์ชันถูกเลิกใช้งาน การตอบกลับจะรวม:

Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"

การค้นหาเวอร์ชัน

Endpoint รูทจะแสดงรายการเวอร์ชันที่มีอยู่:

GET https://petstoreapi.com/

{
  "versions": [
    {
      "version": "v1",
      "status": "current",
      "docsUrl": "https://docs.petstoreapi.com/v1"
    }
  ]
}

การกำหนดเวอร์ชันเชิงความหมาย (Semantic Versioning)

Modern PetstoreAPI ใช้การกำหนดเวอร์ชันเชิงความหมายภายใน:

เฉพาะเวอร์ชันหลักเท่านั้นที่ปรากฏใน URL

การทดสอบเวอร์ชัน API ด้วย Apidog

Apidog ช่วยให้คุณทดสอบ API หลายเวอร์ชันได้

นำเข้าหลายเวอร์ชัน

นำเข้าข้อมูลจำเพาะ OpenAPI สำหรับแต่ละเวอร์ชัน:

petstore-v1.yaml → Environment: v1
petstore-v2.yaml → Environment: v2

รันการทดสอบกับทุกเวอร์ชัน

สร้างชุดทดสอบที่รันกับทั้งสองเวอร์ชัน:

// ทดสอบ v1
pm.environment.set("baseUrl", "https://petstoreapi.com/v1");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");

// ทดสอบ v2
pm.environment.set("baseUrl", "https://petstoreapi.com/v2");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");

ตรวจสอบพฤติกรรมเฉพาะเวอร์ชัน

ทดสอบว่า v1 และ v2 มีพฤติกรรมที่แตกต่างกัน:

// v1 ส่งคืนอาร์เรย์เปล่า
pm.test("v1 returns array", function() {
    pm.expect(pm.response.json()).to.be.an('array');
});

// v2 ส่งคืนออบเจกต์ที่ถูกห่อหุ้ม
pm.test("v2 returns wrapped object", function() {
    pm.expect(pm.response.json()).to.have.property('data');
    pm.expect(pm.response.json()).to.have.property('pagination');
});

ตรวจสอบ Header การเลิกใช้งาน

ทดสอบว่าเวอร์ชันที่ถูกเลิกใช้งานมี Header ที่ถูกต้อง:

pm.test("Deprecated version includes headers", function() {
    pm.response.to.have.header("Deprecation");
    pm.response.to.have.header("Sunset");
});

กลยุทธ์การเลิกใช้งานเวอร์ชัน

วิธีการเลิกใช้งานเวอร์ชันเก่าโดยไม่ทำให้ไคลเอนต์เสียหาย

1. ประกาศการเลิกใช้งานล่วงหน้า

แจ้งไคลเอนต์ล่วงหน้าอย่างน้อย 6-12 เดือน:

Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT

2. จัดเตรียมคู่มือการโยกย้าย

จัดทำเอกสารการเปลี่ยนแปลงที่ส่งผลกระทบทั้งหมดและวิธีการโยกย้าย:

Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"

3. ตรวจสอบการใช้งาน

ติดตามว่าไคลเอนต์ใดที่ยังคงใช้เวอร์ชันที่ถูกเลิกใช้งาน:

X-API-Version: 1.2.0
X-Client-ID: abc123

ติดต่อไคลเอนต์โดยตรงหากจำเป็น

4. ปิดตัวลงอย่างค่อยเป็นค่อยไป

อย่าลบเวอร์ชันทันที:

  1. เดือนที่ 1-6: ประกาศการเลิกใช้งาน
  2. เดือนที่ 7-9: เพิ่ม Header การเลิกใช้งาน
  3. เดือนที่ 10-11: ลดอัตราการจำกัด (rate limits) สำหรับเวอร์ชันที่ถูกเลิกใช้งาน
  4. เดือนที่ 12: ลบเวอร์ชันที่ถูกเลิกใช้งาน

5. เก็บเอกสารประกอบไว้

แม้หลังจากถูกลบออกแล้ว ให้เก็บเอกสารประกอบสำหรับเวอร์ชันเก่าไว้ ไคลเอนต์อาจจำเป็นต้องอ้างอิง

บทสรุป

การกำหนดเวอร์ชันด้วย URL เป็นกลยุทธ์การกำหนดเวอร์ชัน API ที่ใช้งานได้จริงที่สุดสำหรับทีมส่วนใหญ่ สามารถมองเห็นได้, ทดสอบง่าย และทำงานร่วมกับเครื่องมือ HTTP ทั้งหมด การกำหนดเวอร์ชันด้วย Header และ Content negotiation มีความเป็น "REST" ที่บริสุทธิ์กว่า แต่เพิ่มความซับซ้อน

Modern PetstoreAPI ใช้การกำหนดเวอร์ชันด้วย URL โดยมี /v1 เป็นเวอร์ชันปัจจุบัน, การกำหนดเวอร์ชันเชิงความหมายภายใน และนโยบายการเลิกใช้งานที่ชัดเจน แนวทางนี้สร้างสมดุลระหว่างการใช้งานได้จริงกับการออกแบบ API ที่ดี

ใช้ Apidog เพื่อทดสอบ API หลายเวอร์ชัน, ตรวจสอบพฤติกรรมเฉพาะเวอร์ชัน และรับรองการโยกย้ายที่ราบรื่นระหว่างเวอร์ชัน

button

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

ฉันควรใช้การกำหนดเวอร์ชันด้วย URL หรือ Header?

ใช้การกำหนดเวอร์ชันด้วย URL เว้นแต่คุณมีเหตุผลเฉพาะที่จะไม่ใช้ มันง่ายกว่า, มองเห็นได้ชัดเจนกว่า และทดสอบได้ง่ายกว่า การกำหนดเวอร์ชันด้วย Header มีความเป็น "RESTful" มากกว่า แต่เพิ่มความซับซ้อนที่ทีมส่วนใหญ่ไม่จำเป็นต้องมี

ฉันควรรองรับกี่เวอร์ชันพร้อมกัน?

รองรับสูงสุด 2 เวอร์ชัน: ปัจจุบันและเวอร์ชันก่อนหน้า การรองรับมากกว่านั้นจะเพิ่มภาระในการบำรุงรักษา ให้เวลาไคลเอนต์ 6-12 เดือนในการโยกย้าย จากนั้นลบเวอร์ชันเก่าออก

ฉันควรกำหนดเวอร์ชันจาก v0 หรือ v1?

เริ่มต้นด้วย v1 v0 สื่อถึงความไม่เสถียร หาก API ของคุณยังไม่เสถียรพอสำหรับ v1 ก็ยังไม่ต้องเผยแพร่ต่อสาธารณะ

ฉันจำเป็นต้องกำหนดเวอร์ชันทุก Endpoint หรือไม่?

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

แล้วเวอร์ชันรองใน URL ล่ะ?

อย่ารวมเวอร์ชันรองใน URL ใช้ /v1 ไม่ใช่ /v1.2 เวอร์ชันรองนั้นเข้ากันได้ย้อนหลัง ดังนั้นไคลเอนต์ไม่จำเป็นต้องเปลี่ยน URL

ฉันจะจัดการกับข้อผิดพลาดเฉพาะเวอร์ชันได้อย่างไร?

แก้ไขข้อผิดพลาดในทุกเวอร์ชันที่รองรับ หากข้อผิดพลาดมีอยู่ใน v1 เท่านั้น ให้แก้ไขใน v1 อย่าบังคับให้ไคลเอนต์อัปเกรดเป็น v2 เพื่อแก้ไขข้อผิดพลาด

ฉันควรใช้การกำหนดเวอร์ชันเชิงความหมาย (semantic versioning) หรือไม่?

ใช่ ใช้ภายใน ภายในองค์กร ให้ติดตามเวอร์ชัน major.minor.patch แต่ให้แสดงเฉพาะเวอร์ชันหลักใน URL สิ่งนี้จะช่วยให้คุณมีความยืดหยุ่นสำหรับการเปลี่ยนแปลงที่ไม่ส่งผลกระทบ

จะเกิดอะไรขึ้นถ้าฉันต้องการกำหนดเวอร์ชันแค่ Endpoint เดียว?

ด้วยการกำหนดเวอร์ชันด้วย URL คุณจะต้องกำหนดเวอร์ชัน API ทั้งหมดหรือสร้างความไม่สอดคล้องกัน นี่คือข้อแลกเปลี่ยน ทีมส่วนใหญ่ยอมรับการกำหนดเวอร์ชัน API ทั้งหมดเพื่อความเรียบง่าย

ฝึกการออกแบบ API แบบ Design-first ใน Apidog

ค้นพบวิธีที่ง่ายขึ้นในการสร้างและใช้ API