Tóm tắt
URL của REST API nên chứa danh từ (tài nguyên), không phải động từ (hành động). Các phương thức HTTP (GET, POST, PUT, DELETE) là các động từ. Việc sử dụng các động từ hành động như /getUser hoặc /createOrder vi phạm nguyên tắc REST, gây ra sự không nhất quán và làm cho API khó bảo trì hơn. PetstoreAPI hiện đại sử dụng nhất quán các URL định hướng tài nguyên.
Giới thiệu
Bạn đang thiết kế một endpoint API để tìm kiếm thú cưng theo trạng thái. Phản ứng đầu tiên của bạn có thể là: GET /findPetsByStatus?status=available. Nó có tính mô tả, rõ ràng và cho bạn biết chính xác những gì nó làm. Nhưng nó cũng sai.
REST API nên sử dụng danh từ trong URL, không phải động từ. Phương thức HTTP là động từ. GET /pets?status=available là thiết kế đúng. URL đại diện cho tài nguyên (thú cưng), và phương thức đại diện cho hành động (lấy).
Swagger Petstore cũ đã mắc lỗi này với các endpoint như /pet/findByStatus và /pet/findByTags. Các động từ hành động trong URL này vi phạm nguyên tắc REST và tạo ra các vấn đề bảo trì. PetstoreAPI hiện đại khắc phục điều này bằng cách sử dụng các URL định hướng tài nguyên một cách nhất quán.
Trong hướng dẫn này, bạn sẽ tìm hiểu lý do tại sao động từ không thuộc về URL của REST, cách thiết kế các endpoint định hướng tài nguyên và cách PetstoreAPI hiện đại triển khai điều này một cách chính xác.
Vấn đề động từ trong REST API
Các động từ hành động trong URL cho thấy bạn đang suy nghĩ theo thuật ngữ RPC (Remote Procedure Call), chứ không phải thuật ngữ REST.
URL kiểu RPC (Sai)
POST /createUser
GET /getUser?id=123
PUT /updateUser
DELETE /deleteUser?id=123
GET /findUsersByRole?role=admin
POST /sendEmail
GET /calculateTotal
Các URL này mô tả các hành động. Chúng đọc giống như các lệnh gọi hàm: createUser(), getUser(), sendEmail().
URL kiểu REST (Đúng)
POST /users
GET /users/123
PUT /users/123
DELETE /users/123
GET /users?role=admin
POST /emails
GET /orders/123/total
Các URL này mô tả các tài nguyên. Phương thức HTTP cung cấp hành động.
Tại sao điều này quan trọng
Tính nhất quán: URL của REST tuân theo một mẫu có thể dự đoán. Khi bạn biết tên tài nguyên, bạn biết tất cả các endpoint:
GET /pets- Liệt kê thú cưngPOST /pets- Tạo thú cưngGET /pets/{id}- Lấy thông tin thú cưngPUT /pets/{id}- Cập nhật thú cưngDELETE /pets/{id}- Xóa thú cưng
Với các URL dựa trên động từ, mỗi endpoint là duy nhất. Không có mẫu nào để tuân theo.
Khả năng mở rộng: Khi API của bạn phát triển, các URL dựa trên động từ sẽ nhân lên:
/findPetsByStatus/findPetsByTags/findPetsByOwner/findPetsByBreed/searchPets/queryPets
Các URL định hướng tài nguyên sử dụng các tham số truy vấn:
GET /pets?status=availableGET /pets?tags=friendlyGET /pets?owner=johnGET /pets?breed=labrador
Một endpoint xử lý tất cả các bộ lọc.
Tại sao các phương thức HTTP là các động từ
REST tận dụng các động từ tích hợp sẵn của HTTP. Bạn không cần phải tự tạo ra động từ của riêng mình.
Các phương thức HTTP ánh xạ tới các hoạt động CRUD
POST → Tạo
GET → Đọc
PUT → Cập nhật (thay thế)
PATCH → Cập nhật (một phần)
DELETE → Xóa
Các phương thức này có ngữ nghĩa được định nghĩa. GET an toàn và bất biến (idempotent). POST tạo tài nguyên. DELETE loại bỏ chúng.
Ví dụ: Quản lý người dùng
Sai (động từ trong URL):
POST /createUser
GET /getUser?id=123
POST /updateUser
POST /deleteUser
Mỗi hoạt động sử dụng một URL khác nhau. Phương thức HTTP không truyền đạt ý nghĩa.
Đúng (phương thức HTTP làm động từ):
POST /users ← Tạo người dùng
GET /users/123 ← Lấy thông tin người dùng
PUT /users/123 ← Cập nhật người dùng
DELETE /users/123 ← Xóa người dùng
URL giữ nguyên. Phương thức thay đổi.
Lợi ích của việc sử dụng các phương thức HTTP
1. Bộ nhớ đệm (Caching): Các yêu cầu GET có thể được lưu vào bộ nhớ đệm. Trình duyệt và proxy biết điều này. Nếu bạn sử dụng POST /getUser, việc lưu vào bộ nhớ đệm sẽ bị hỏng.
2. Tính bất biến (Idempotency): PUT và DELETE có tính bất biến. Gọi chúng nhiều lần có cùng một hiệu ứng như gọi một lần. Điều này quan trọng đối với logic thử lại.
3. An toàn: GET an toàn—nó không thay đổi trạng thái. Các công cụ và trình thu thập dữ liệu có thể an toàn gọi các endpoint GET.
4. Tuân thủ tiêu chuẩn: Các máy khách HTTP, proxy và bộ nhớ đệm hiểu các phương thức HTTP. Chúng không hiểu các động từ tùy chỉnh của bạn.
Ví dụ thực tế từ Swagger Petstore
Swagger Petstore cũ bao gồm một số endpoint dựa trên động từ.
Ví dụ 1: Tìm thú cưng theo trạng thái
Swagger Petstore (Sai):
GET /pet/findByStatus?status=available
Vấn đề:
findByStatuslà một cụm động từ- Không nhất quán với endpoint
/pet/{id} - Không thể mở rộng dễ dàng (còn việc tìm kiếm theo các tiêu chí khác thì sao?)
PetstoreAPI hiện đại (Đúng):
GET /pets?status=AVAILABLE
Lợi ích:
- Định hướng tài nguyên (
/pets) - Sử dụng tham số truy vấn để lọc
- Nhất quán với các endpoint khác
- Dễ dàng mở rộng:
GET /pets?status=AVAILABLE&species=dog
Xem tài liệu REST của PetstoreAPI hiện đại để biết triển khai đầy đủ.
Ví dụ 2: Tìm thú cưng bằng thẻ
Swagger Petstore (Sai):
GET /pet/findByTags?tags=tag1,tag2
PetstoreAPI hiện đại (Đúng):
GET /pets?tags=friendly,trained
Ví dụ 3: Đăng nhập người dùng
Swagger Petstore (Sai):
GET /user/login?username=john&password=secret
Nhiều vấn đề:
loginlà một động từ- Sử dụng
GETđể xác thực (thảm họa bảo mật) - Mật khẩu trong tham số truy vấn URL
PetstoreAPI hiện đại (Đúng):
POST /auth/login
Content-Type: application/json
{
"username": "john",
"password": "secret123"
}
Lợi ích:
- Định hướng tài nguyên (
/auth) - Phương thức HTTP chính xác (
POST) - Thông tin xác thực trong phần thân yêu cầu, không phải URL
- Trả về token JWT cho các yêu cầu tiếp theo
Cách PetstoreAPI hiện đại khắc phục điều này
PetstoreAPI hiện đại sử dụng nhất quán các URL định hướng tài nguyên.
Quản lý thú cưng
GET /pets ← Liệt kê tất cả thú cưng
GET /pets?status=AVAILABLE ← Lọc theo trạng thái
GET /pets?species=dog ← Lọc theo loài
GET /pets/{id} ← Lấy thông tin thú cưng cụ thể
POST /pets ← Tạo thú cưng mới
PUT /pets/{id} ← Cập nhật thú cưng
PATCH /pets/{id} ← Cập nhật một phần
DELETE /pets/{id} ← Xóa thú cưng
Không có động từ. Chỉ có tài nguyên và phương thức HTTP.
Quản lý đơn hàng
GET /orders ← Liệt kê đơn hàng
GET /orders/{id} ← Lấy thông tin đơn hàng
POST /orders ← Tạo đơn hàng
PUT /orders/{id} ← Cập nhật đơn hàng
DELETE /orders/{id} ← Hủy đơn hàng
GET /orders/{id}/items ← Lấy các mặt hàng trong đơn hàng
Các hoạt động phức tạp
Đối với các hoạt động không ánh xạ rõ ràng tới CRUD, PetstoreAPI hiện đại sử dụng các tài nguyên con:
POST /orders/{id}/payment ← Xử lý thanh toán cho đơn hàng
POST /orders/{id}/shipment ← Tạo vận chuyển cho đơn hàng
POST /pets/{id}/adoption ← Bắt đầu quy trình nhận nuôi
Những điều này vẫn định hướng tài nguyên. /orders/{id}/payment đại diện cho tài nguyên thanh toán cho một đơn hàng.
Khi động từ có vẻ cần thiết
Một số hoạt động không phù hợp với mô hình CRUD. Đây là cách xử lý chúng mà không cần động từ trong URL.
Các hoạt động tìm kiếm
Sai:
GET /searchPets?query=labrador
Tùy chọn đúng 1 (Tham số truy vấn):
GET /pets?search=labrador
Tùy chọn đúng 2 (Tài nguyên tìm kiếm):
GET /pets/search?q=labrador
Tùy chọn đúng 3 (Phương thức QUERY):
QUERY /pets
Content-Type: application/json
{
"query": "labrador",
"filters": {
"status": "AVAILABLE"
}
}
PetstoreAPI hiện đại hỗ trợ cả ba mẫu tùy thuộc vào độ phức tạp.
Tính toán
Sai:
GET /calculateShipping?weight=10&destination=NY
Đúng:
GET /shipping-estimates?weight=10&destination=NY
Tài nguyên là "ước tính vận chuyển", không phải hành động tính toán.
Các hoạt động hàng loạt
Sai:
POST /batchDeletePets
Đúng:
DELETE /pets?ids=1,2,3
Hoặc sử dụng tài nguyên hàng loạt:
POST /pets/batch-operations
Content-Type: application/json
{
"operation": "delete",
"ids": [1, 2, 3]
}
Các hành động thay đổi trạng thái
Sai:
POST /activateUser
POST /deactivateUser
Đúng:
PATCH /users/{id}
Content-Type: application/json
{
"status": "ACTIVE"
}
Thay đổi trạng thái là cập nhật tài nguyên.
Kiểm tra thiết kế URL với Apidog
Apidog giúp bạn xác thực thiết kế REST API và phát hiện việc sử dụng động từ trong URL.
Nhập PetstoreAPI hiện đại
- Nhập đặc tả OpenAPI của PetstoreAPI hiện đại
- Apidog tự động tạo các trường hợp thử nghiệm
- Xem lại cấu trúc và cách đặt tên endpoint
Kiểm tra động từ trong URL
Tạo một quy tắc xác thực tùy chỉnh trong Apidog:
// Kiểm tra xem URL có chứa các động từ hành động phổ biến không
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 chứa động từ: ${verb}. Thay vào đó, hãy sử dụng URL định hướng tài nguyên.`);
}
}
Kiểm tra tính nhất quán của Endpoint
Apidog có thể xác minh rằng các endpoint liên quan tuân theo các mẫu nhất quán:
✓ GET /pets
✓ POST /pets
✓ GET /pets/{id}
✓ PUT /pets/{id}
✓ DELETE /pets/{id}
Tất cả đều sử dụng cùng tài nguyên cơ sở (/pets).
So sánh với PetstoreAPI hiện đại
- Nhập cả API của bạn và PetstoreAPI hiện đại vào Apidog
- So sánh cấu trúc endpoint cạnh nhau
- Xác định sự không nhất quán và việc sử dụng động từ
- Tái cấu trúc API của bạn để phù hợp với nguyên tắc REST
Chiến lược di chuyển
Nếu bạn có một API hiện có với các động từ trong URL, đây là cách để di chuyển.
Chiến lược 1: Định phiên bản
Tạo một phiên bản API mới với các URL chính xác:
# API cũ (v1)
GET /api/v1/findPetsByStatus?status=available
# API mới (v2)
GET /api/v2/pets?status=available
Duy trì v1 để tương thích ngược, khuyến khích di chuyển sang v2.
Chiến lược 2: Tạo bí danh
Tạm thời hỗ trợ cả URL cũ và mới:
# URL cũ (không dùng nữa)
GET /pet/findByStatus?status=available
# URL mới (ưu tiên)
GET /pets?status=available
Trả về cảnh báo không dùng nữa trong các phản hồi:
{
"data": [...],
"warnings": [
{
"code": "DEPRECATED_ENDPOINT",
"message": "Endpoint này không còn được dùng nữa. Thay vào đó, hãy sử dụng GET /pets?status=available.",
"sunset": "2027-01-01"
}
]
}
Chiến lược 3: Chuyển hướng
Sử dụng chuyển hướng HTTP 301 cho các lần di chuyển đơn giản:
GET /pet/findByStatus?status=available
→ 301 Đã di chuyển vĩnh viễn
Location: /pets?status=available
Điều này hoạt động cho các yêu cầu GET nhưng không phải cho POST, PUT hoặc DELETE.
Kết luận
URL của REST API nên chứa danh từ (tài nguyên), không phải động từ (hành động). Các phương thức HTTP cung cấp các động từ. Nguyên tắc này tạo ra các API nhất quán, có khả năng mở rộng và dễ bảo trì.
Swagger Petstore cũ đã vi phạm điều này với các endpoint như /pet/findByStatus. PetstoreAPI hiện đại khắc phục điều này bằng cách sử dụng nhất quán các URL định hướng tài nguyên: /pets?status=AVAILABLE.
Những điểm chính:
- Sử dụng danh từ trong URL:
/pets,/orders,/users - Hãy để các phương thức HTTP là các động từ:
GET,POST,PUT,DELETE - Sử dụng tham số truy vấn để lọc:
/pets?status=available - Đối với các hoạt động phức tạp, hãy sử dụng tài nguyên con:
/orders/{id}/payment - Kiểm tra thiết kế API của bạn với Apidog để phát hiện sớm việc sử dụng động từ
Xem tài liệu PetstoreAPI hiện đại để biết các ví dụ đầy đủ về thiết kế URL định hướng tài nguyên.
Câu hỏi thường gặp
Tôi có thể sử dụng động từ trong URL của REST không?
Hiếm khi. Nếu một hoạt động thực sự không phù hợp với mô hình tài nguyên (như /search hoặc /login), một động từ có thể được chấp nhận. Nhưng 95% thời gian, bạn có thể mô hình hóa nó như một tài nguyên.
Còn /login và /logout thì sao?
Đây là những trường hợp ngoại lệ phổ biến. Nhiều API sử dụng /auth/login và /auth/logout. Thay vào đó, hãy mô hình hóa chúng như các tài nguyên: POST /sessions (đăng nhập) và DELETE /sessions/{id} (đăng xuất).
Làm thế nào để xử lý các truy vấn phức tạp?
Sử dụng tham số truy vấn để lọc đơn giản: /pets?status=available&species=dog. Đối với các truy vấn phức tạp, hãy sử dụng phương thức HTTP QUERY hoặc tài nguyên tìm kiếm: POST /pets/search.
Điều gì sẽ xảy ra nếu hoạt động của tôi không ánh xạ tới CRUD?
Mô hình hóa nó như một tài nguyên con. Thay vì POST /processPayment, hãy sử dụng POST /orders/{id}/payment. Thanh toán là một tài nguyên liên quan đến đơn hàng.
Làm cách nào để kiểm tra xem URL của tôi có định hướng tài nguyên không?
Sử dụng Apidog để nhập đặc tả OpenAPI của bạn và kiểm tra động từ trong URL. So sánh cấu trúc API của bạn với PetstoreAPI hiện đại làm tài liệu tham khảo.
Tôi nên sử dụng /pets/search hay /pets?search=query?
Cả hai đều chấp nhận được. /pets?search=query đơn giản hơn cho tìm kiếm cơ bản. /pets/search hoặc QUERY /pets hoạt động tốt hơn cho tìm kiếm phức tạp với nhiều tham số.
Làm cách nào để di chuyển từ URL dựa trên động từ?
Sử dụng định phiên bản API (/v2/pets thay vì /v1/findPets), thêm cảnh báo không dùng nữa và cho khách hàng thời gian để di chuyển. Xem phần Chiến lược di chuyển để biết chi tiết.
PetstoreAPI hiện đại có sử dụng bất kỳ động từ nào trong URL không?
PetstoreAPI hiện đại tránh sử dụng động từ trong URL. Các hoạt động như tìm kiếm, lọc và xác thực được mô hình hóa thành tài nguyên hoặc sử dụng các tham số truy vấn. Kiểm tra tài liệu REST API để biết ví dụ.
