ทำไมไม่ควรใช้คำกริยาใน URL ของ REST API

Ashley Innocent

Ashley Innocent

13 March 2026

ทำไมไม่ควรใช้คำกริยาใน URL ของ REST API

Apidog สำหรับองค์กร

ติดตั้งภายในองค์กร

SSO & RBAC

รองรับ SOC 2

สำรวจ Apidog Enterprise

สรุปโดยย่อ

URL ของ REST API ควรมีคำนาม (ทรัพยากร) ไม่ใช่คำกริยา (การกระทำ) เมธอด HTTP (GET, POST, PUT, DELETE) คือคำกริยา การใช้คำกริยาที่บ่งบอกการกระทำ เช่น /getUser หรือ /createOrder เป็นการละเมิดหลักการของ REST, ทำให้เกิดความไม่สอดคล้องกัน และทำให้ API บำรุงรักษายากขึ้น Modern PetstoreAPI ใช้ URL ที่เน้นทรัพยากรตลอดทั้งระบบ

บทนำ

คุณกำลังออกแบบ API endpoint เพื่อค้นหาสัตว์เลี้ยงตามสถานะ สัญชาตญาณแรกของคุณอาจเป็น: GET /findPetsByStatus?status=available ซึ่งเป็นคำอธิบายที่ชัดเจนและบอกได้ว่าทำอะไรได้บ้าง แต่มันผิด

REST API ควรใช้คำนามใน URL ไม่ใช่คำกริยา เมธอด HTTP คือคำกริยา GET /pets?status=available คือการออกแบบที่ถูกต้อง URL แสดงถึงทรัพยากร (สัตว์เลี้ยง) และเมธอดแสดงถึงการกระทำ (รับข้อมูล)

Swagger Petstore รุ่นเก่าทำผิดพลาดตรงนี้ด้วย endpoint เช่น /pet/findByStatus และ /pet/findByTags การใช้คำกริยาที่บ่งบอกการกระทำใน URL เหล่านี้ละเมิดหลักการของ REST และสร้างปัญหาในการบำรุงรักษา Modern PetstoreAPI แก้ไขปัญหานี้โดยใช้ URL ที่เน้นทรัพยากรอย่างสม่ำเสมอ

💡
หากคุณกำลังสร้างหรือทดสอบ REST API, Apidog ช่วยให้คุณตรวจสอบความถูกต้องของการออกแบบ URL, ทดสอบพฤติกรรมของ endpoint, และทำให้แน่ใจว่า API ของคุณปฏิบัติตามหลักการของ REST คุณสามารถนำเข้า OpenAPI spec, ตรวจสอบการใช้คำกริยาใน URL, และตรวจพบปัญหาการออกแบบได้ตั้งแต่เนิ่นๆ
ปุ่ม

ในคู่มือนี้ คุณจะได้เรียนรู้ว่าทำไมคำกริยาจึงไม่ควรอยู่ใน URL ของ REST, วิธีการออกแบบ endpoint ที่เน้นทรัพยากร, และวิธีที่ Modern PetstoreAPI นำสิ่งนี้ไปใช้อย่างถูกต้อง

ปัญหาคำกริยาใน REST API

คำกริยาที่บ่งบอกการกระทำใน URL แสดงว่าคุณกำลังคิดในแง่ของ RPC (Remote Procedure Call) ไม่ใช่ในแง่ของ REST

URL สไตล์ RPC (ผิด)

POST /createUser
GET /getUser?id=123
PUT /updateUser
DELETE /deleteUser?id=123
GET /findUsersByRole?role=admin
POST /sendEmail
GET /calculateTotal

URL เหล่านี้อธิบายถึงการกระทำ พวกมันอ่านเหมือนการเรียกฟังก์ชัน: createUser(), getUser(), sendEmail()

URL สไตล์ REST (ถูกต้อง)

POST /users
GET /users/123
PUT /users/123
DELETE /users/123
GET /users?role=admin
POST /emails
GET /orders/123/total

URL เหล่านี้อธิบายถึงทรัพยากร เมธอด HTTP ให้การกระทำ

ทำไมเรื่องนี้ถึงสำคัญ

ความสอดคล้องกัน: URL ของ REST มีรูปแบบที่คาดเดาได้ เมื่อคุณรู้ชื่อทรัพยากร คุณก็จะรู้ endpoint ทั้งหมด:

ด้วย URL ที่อิงคำกริยา ทุก endpoint จะไม่ซ้ำกัน ไม่มีรูปแบบให้ปฏิบัติตาม

ความสามารถในการขยายขนาด: เมื่อ API ของคุณเติบโตขึ้น URL ที่อิงคำกริยาก็จะเพิ่มจำนวนขึ้น:

URL ที่เน้นทรัพยากรใช้พารามิเตอร์การค้นหา:

มี endpoint เดียวที่จัดการการกรองทั้งหมด

ทำไมเมธอด HTTP ถึงเป็นคำกริยา

REST ใช้ประโยชน์จากคำกริยาในตัวของ HTTP คุณไม่จำเป็นต้องสร้างขึ้นมาเอง

เมธอด HTTP สอดคล้องกับการดำเนินการ CRUD

POST   → สร้าง
GET    → อ่าน
PUT    → อัปเดต (แทนที่)
PATCH  → อัปเดต (บางส่วน)
DELETE → ลบ

เมธอดเหล่านี้มีความหมายที่กำหนดไว้ GET ปลอดภัยและ idempotent POST สร้างทรัพยากร DELETE ลบทรัพยากร

ตัวอย่าง: การจัดการผู้ใช้

ผิด (คำกริยาใน URL):

POST /createUser
GET /getUser?id=123
POST /updateUser
POST /deleteUser

ทุกการดำเนินการใช้ URL ที่แตกต่างกัน เมธอด HTTP ไม่สื่อความหมาย

ถูกต้อง (เมธอด HTTP เป็นคำกริยา):

POST /users           ← สร้างผู้ใช้
GET /users/123        ← รับข้อมูลผู้ใช้
PUT /users/123        ← อัปเดตผู้ใช้
DELETE /users/123     ← ลบผู้ใช้

URL ยังคงเดิม เมธอดเปลี่ยนแปลง

ประโยชน์ของการใช้เมธอด HTTP

1. การแคช: คำขอ GET สามารถถูกแคชได้ เบราว์เซอร์และพร็อกซีรู้เรื่องนี้ หากคุณใช้ POST /getUser การแคชจะทำงานผิดพลาด

2. Idempotency: PUT และ DELETE เป็นแบบ idempotent การเรียกใช้หลายครั้งมีผลเช่นเดียวกับการเรียกใช้ครั้งเดียว สิ่งนี้มีความสำคัญสำหรับตรรกะการลองใหม่

3. ความปลอดภัย: GET ปลอดภัย—ไม่เปลี่ยนแปลงสถานะ เครื่องมือและเว็บครอว์เลอร์สามารถเรียกใช้ endpoint แบบ GET ได้อย่างปลอดภัย

4. การปฏิบัติตามมาตรฐาน: ไคลเอนต์ HTTP, พร็อกซี, และแคชเข้าใจเมธอด HTTP พวกเขาไม่เข้าใจคำกริยาที่คุณกำหนดเอง

ตัวอย่างจริงจาก Swagger Petstore

Swagger Petstore รุ่นเก่ามี endpoint ที่อิงคำกริยาหลายรายการ

ตัวอย่างที่ 1: การค้นหาสัตว์เลี้ยงตามสถานะ

Swagger Petstore (ผิด):

GET /pet/findByStatus?status=available

ปัญหา:

Modern PetstoreAPI (ถูกต้อง):

GET /pets?status=AVAILABLE

ประโยชน์:

ดู เอกสาร REST ของ Modern PetstoreAPI สำหรับการใช้งานที่สมบูรณ์

ตัวอย่างที่ 2: การค้นหาสัตว์เลี้ยงตามแท็ก

Swagger Petstore (ผิด):

GET /pet/findByTags?tags=tag1,tag2

Modern PetstoreAPI (ถูกต้อง):

GET /pets?tags=friendly,trained

ตัวอย่างที่ 3: การเข้าสู่ระบบผู้ใช้

Swagger Petstore (ผิด):

GET /user/login?username=john&password=secret

ปัญหาหลายประการ:

Modern PetstoreAPI (ถูกต้อง):

POST /auth/login
Content-Type: application/json

{
  "username": "john",
  "password": "secret123"
}

ประโยชน์:

Modern PetstoreAPI แก้ไขปัญหานี้อย่างไร

Modern PetstoreAPI ใช้ URL ที่เน้นทรัพยากรตลอดทั้งระบบ

การจัดการสัตว์เลี้ยง

GET /pets                    ← แสดงสัตว์เลี้ยงทั้งหมด
GET /pets?status=AVAILABLE   ← กรองตามสถานะ
GET /pets?species=dog        ← กรองตามชนิด
GET /pets/{id}               ← รับข้อมูลสัตว์เลี้ยงเฉพาะ
POST /pets                   ← สร้างสัตว์เลี้ยงใหม่
PUT /pets/{id}               ← อัปเดตสัตว์เลี้ยง
PATCH /pets/{id}             ← อัปเดตบางส่วน
DELETE /pets/{id}            ← ลบสัตว์เลี้ยง

ไม่มีคำกริยา มีเพียงทรัพยากรและเมธอด HTTP

การจัดการคำสั่งซื้อ

GET /orders                  ← แสดงรายการคำสั่งซื้อ
GET /orders/{id}             ← รับคำสั่งซื้อ
POST /orders                 ← สร้างคำสั่งซื้อ
PUT /orders/{id}             ← อัปเดตคำสั่งซื้อ
DELETE /orders/{id}          ← ยกเลิกคำสั่งซื้อ
GET /orders/{id}/items       ← รับรายการสินค้าในคำสั่งซื้อ

การดำเนินการที่ซับซ้อน

สำหรับการดำเนินการที่ไม่สอดคล้องกับ CRUD อย่างชัดเจน Modern PetstoreAPI ใช้ทรัพยากรย่อย:

POST /orders/{id}/payment    ← ประมวลผลการชำระเงินสำหรับคำสั่งซื้อ
POST /orders/{id}/shipment   ← สร้างการจัดส่งสำหรับคำสั่งซื้อ
POST /pets/{id}/adoption     ← เริ่มกระบวนการรับเลี้ยงบุตรบุญธรรม

สิ่งเหล่านี้ยังคงเน้นทรัพยากร /orders/{id}/payment แสดงถึงทรัพยากรการชำระเงินสำหรับคำสั่งซื้อ

เมื่อคำกริยาดูเหมือนจำเป็น

การดำเนินการบางอย่างไม่เหมาะกับโมเดล CRUD นี่คือวิธีการจัดการโดยไม่มีคำกริยาใน URL

การดำเนินการค้นหา

ผิด:

GET /searchPets?query=labrador

ตัวเลือกที่ถูกต้อง 1 (พารามิเตอร์การค้นหา):

GET /pets?search=labrador

ตัวเลือกที่ถูกต้อง 2 (ทรัพยากรการค้นหา):

GET /pets/search?q=labrador

ตัวเลือกที่ถูกต้อง 3 (เมธอด QUERY):

QUERY /pets
Content-Type: application/json

{
  "query": "labrador",
  "filters": {
    "status": "AVAILABLE"
  }
}

Modern PetstoreAPI รองรับทั้งสามรูปแบบขึ้นอยู่กับความซับซ้อน

การคำนวณ

ผิด:

GET /calculateShipping?weight=10&destination=NY

ถูกต้อง:

GET /shipping-estimates?weight=10&destination=NY

ทรัพยากรคือ "ประมาณการค่าจัดส่ง" ไม่ใช่การกระทำในการคำนวณ

การดำเนินการแบบกลุ่ม

ผิด:

POST /batchDeletePets

ถูกต้อง:

DELETE /pets?ids=1,2,3

หรือใช้ทรัพยากรแบบกลุ่ม:

POST /pets/batch-operations
Content-Type: application/json

{
  "operation": "delete",
  "ids": [1, 2, 3]
}

การกระทำที่เปลี่ยนแปลงสถานะ

ผิด:

POST /activateUser
POST /deactivateUser

ถูกต้อง:

PATCH /users/{id}
Content-Type: application/json

{
  "status": "ACTIVE"
}

การเปลี่ยนแปลงสถานะคือการอัปเดตทรัพยากร

การทดสอบการออกแบบ URL ด้วย Apidog

Apidog ช่วยให้คุณตรวจสอบความถูกต้องของการออกแบบ REST API และตรวจจับการใช้คำกริยาใน URL

นำเข้า Modern PetstoreAPI

  1. นำเข้า OpenAPI spec ของ Modern PetstoreAPI
  2. Apidog สร้างกรณีทดสอบโดยอัตโนมัติ
  3. ตรวจสอบโครงสร้างและการตั้งชื่อ endpoint

ตรวจสอบคำกริยาใน URL

สร้างกฎการตรวจสอบแบบกำหนดเองใน Apidog:

// ตรวจสอบว่า URL มีคำกริยาที่บ่งบอกการกระทำทั่วไปหรือไม่
const verbs = ['get', 'create', 'update', 'delete', 'find', 'search',
               'calculate', 'process', 'send', 'fetch'];
const url = request.url.toLowerCase();

for (const verb of verbs) {
  if (url.includes(`/${verb}`)) {
    throw new Error(`URL มีคำกริยา: ${verb} ให้ใช้ URL ที่เน้นทรัพยากรแทน`);
  }
}

ทดสอบความสอดคล้องของ Endpoint

Apidog สามารถตรวจสอบได้ว่า endpoint ที่เกี่ยวข้องปฏิบัติตามรูปแบบที่สอดคล้องกัน:

✓ GET /pets
✓ POST /pets
✓ GET /pets/{id}
✓ PUT /pets/{id}
✓ DELETE /pets/{id}

ทั้งหมดใช้ทรัพยากรฐานเดียวกัน (/pets)

เปรียบเทียบกับ Modern PetstoreAPI

  1. นำเข้า API ของคุณและ Modern PetstoreAPI เข้าสู่ Apidog
  2. เปรียบเทียบโครงสร้าง endpoint เคียงข้างกัน
  3. ระบุความไม่สอดคล้องกันและการใช้คำกริยา
  4. ปรับปรุง API ของคุณให้ตรงกับหลักการของ REST

กลยุทธ์การย้ายระบบ

หากคุณมี API ที่มีอยู่ซึ่งใช้คำกริยาใน URL นี่คือวิธีที่จะย้ายระบบ

กลยุทธ์ที่ 1: การกำหนดเวอร์ชัน

สร้าง API เวอร์ชันใหม่ด้วย URL ที่ถูกต้อง:

# API เก่า (v1)
GET /api/v1/findPetsByStatus?status=available

# API ใหม่ (v2)
GET /api/v2/pets?status=available

บำรุงรักษา v1 เพื่อความเข้ากันได้แบบย้อนหลัง และส่งเสริมให้ย้ายไปใช้ v2

กลยุทธ์ที่ 2: การตั้งชื่อแทน (Aliasing)

รองรับทั้ง URL เก่าและใหม่ชั่วคราว:

# URL เก่า (เลิกใช้แล้ว)
GET /pet/findByStatus?status=available

# URL ใหม่ (ที่แนะนำ)
GET /pets?status=available

ส่งคืนคำเตือนการเลิกใช้งานในการตอบกลับ:

{
  "data": [...],
  "warnings": [
    {
      "code": "DEPRECATED_ENDPOINT",
      "message": "endpoint นี้เลิกใช้งานแล้ว โปรดใช้ GET /pets?status=available แทน",
      "sunset": "2027-01-01"
    }
  ]
}

กลยุทธ์ที่ 3: การเปลี่ยนเส้นทาง (Redirects)

ใช้ HTTP 301 redirects สำหรับการย้ายระบบที่ไม่ซับซ้อน:

GET /pet/findByStatus?status=available
→ 301 ถูกย้ายถาวร
Location: /pets?status=available

วิธีนี้ใช้ได้กับคำขอ GET แต่ใช้ไม่ได้กับ POST, PUT, หรือ DELETE

บทสรุป

URL ของ REST API ควรมีคำนาม (ทรัพยากร) ไม่ใช่คำกริยา (การกระทำ) เมธอด HTTP ให้คำกริยา หลักการนี้สร้าง API ที่สอดคล้องกัน ขยายขนาดได้ และบำรุงรักษาง่าย

Swagger Petstore รุ่นเก่าละเมิดหลักการนี้ด้วย endpoint เช่น /pet/findByStatus Modern PetstoreAPI แก้ไขปัญหานี้โดยใช้ URL ที่เน้นทรัพยากรตลอดทั้งระบบ: /pets?status=AVAILABLE

ประเด็นสำคัญ:

ดู เอกสารประกอบ Modern PetstoreAPI สำหรับตัวอย่างที่สมบูรณ์ของการออกแบบ URL ที่เน้นทรัพยากร

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

ฉันสามารถใช้คำกริยาใน URL ของ REST ได้เลยหรือไม่?

ไม่ค่อยบ่อยนัก หากการดำเนินการนั้นไม่เข้ากับโมเดลทรัพยากรอย่างแท้จริง (เช่น /search หรือ /login) การใช้คำกริยาอาจเป็นที่ยอมรับได้ แต่ 95% ของเวลา คุณสามารถสร้างมันเป็นทรัพยากรได้

แล้ว /login และ /logout ล่ะ?

สิ่งเหล่านี้เป็นข้อยกเว้นทั่วไป API จำนวนมากใช้ /auth/login และ /auth/logout อีกทางเลือกหนึ่งคือ สร้างมันเป็นทรัพยากร: POST /sessions (เข้าสู่ระบบ) และ DELETE /sessions/{id} (ออกจากระบบ)

ฉันจะจัดการกับคำค้นที่ซับซ้อนได้อย่างไร?

ใช้พารามิเตอร์การค้นหาสำหรับการกรองแบบง่าย: /pets?status=available&species=dog สำหรับคำค้นที่ซับซ้อน ให้ใช้เมธอด HTTP QUERY หรือทรัพยากรการค้นหา: POST /pets/search

จะทำอย่างไรหากการดำเนินการของฉันไม่สอดคล้องกับ CRUD?

สร้างมันเป็นทรัพยากรย่อย แทนที่จะเป็น POST /processPayment ให้ใช้ POST /orders/{id}/payment การชำระเงินเป็นทรัพยากรที่เกี่ยวข้องกับคำสั่งซื้อ

ฉันจะทดสอบได้อย่างไรว่า URL ของฉันเน้นทรัพยากร?

ใช้ Apidog เพื่อนำเข้า OpenAPI spec ของคุณและตรวจสอบคำกริยาใน URL เปรียบเทียบโครงสร้าง API ของคุณกับ Modern PetstoreAPI เพื่อใช้อ้างอิง

ฉันควรใช้ /pets/search หรือ /pets?search=query?

ทั้งสองแบบเป็นที่ยอมรับได้ /pets?search=query นั้นง่ายกว่าสำหรับการค้นหาพื้นฐาน /pets/search หรือ QUERY /pets ทำงานได้ดีกว่าสำหรับการค้นหาที่ซับซ้อนซึ่งมีพารามิเตอร์หลายตัว

ฉันจะย้ายจาก URL ที่อิงคำกริยาได้อย่างไร?

ใช้การกำหนดเวอร์ชัน API (/v2/pets แทน /v1/findPets), เพิ่มคำเตือนการเลิกใช้งาน, และให้เวลาไคลเอนต์ในการย้ายระบบ ดูรายละเอียดในส่วนกลยุทธ์การย้ายระบบ

Modern PetstoreAPI ใช้คำกริยาใดๆ ใน URL หรือไม่?

Modern PetstoreAPI หลีกเลี่ยงการใช้คำกริยาใน URL การดำเนินการต่างๆ เช่น การค้นหา, การกรอง, และการยืนยันตัวตน ถูกจำลองเป็นทรัพยากรหรือใช้พารามิเตอร์การค้นหา ตรวจสอบ เอกสาร REST API สำหรับตัวอย่าง

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

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