VISEN GROUP
Technology & Engineering

REST API: Thiết kế API như thế nào để dễ sử dụng và mở rộng?

September 23, 20266 min readUncategorized

Một API có thể chạy đúng nhưng vẫn là một API khó sử dụng.

Ví dụ:

GET /getAllUsers
POST /createNewUser
POST /deleteUser

Nhìn vào endpoint, frontend vẫn có thể gọi được. Nhưng khi hệ thống lớn lên, cách đặt tên và thiết kế như vậy dễ tạo ra sự thiếu nhất quán.

Một REST API tốt không chỉ trả về đúng dữ liệu. Nó cần có quy ước rõ ràng, dễ đoán và có khả năng mở rộng.

1. Thiết kế endpoint theo Resource, không theo Action

Một lỗi khá phổ biến là đặt endpoint giống như tên function:

GET  /getUsers
POST /createUser
POST /deleteUser
POST /updateUser

Thay vào đó, hãy coi users là một resource:

GET    /users
POST   /users
GET    /users/123
PATCH  /users/123
DELETE /users/123

Ở đây:

  • GET /users → lấy danh sách user
  • POST /users → tạo user
  • GET /users/123 → lấy user có ID 123
  • PATCH /users/123 → cập nhật user
  • DELETE /users/123 → xóa user

Điểm quan trọng là HTTP Method thể hiện hành động, còn URL thể hiện resource.

Thay vì:

POST /deleteUser

hãy dùng:

DELETE /users/123

Cách này giúp API dễ đoán hơn: chỉ cần biết resource và HTTP Method, developer có thể suy ra cách sử dụng endpoint.


2. Dùng HTTP Method đúng mục đích

Các Method thường gặp:

MethodMục đích
GETLấy dữ liệu
POSTTạo resource hoặc thực hiện một operation phù hợp
PUTThay thế toàn bộ resource
PATCHCập nhật một phần resource
DELETEXóa resource

Ví dụ:

GET /products

→ Lấy danh sách sản phẩm.

POST /products

→ Tạo sản phẩm.

PATCH /products/123

→ Cập nhật một vài thông tin của sản phẩm 123.

DELETE /products/123

→ Xóa sản phẩm 123.

Không nên biến tất cả thao tác thành:

POST /products/update
POST /products/delete
POST /products/get

khi không có lý do đặc biệt.


3. Thiết kế Response nhất quán

Một API có thể có endpoint này trả:

{
  "id": 123,
  "name": "Laptop"
}

nhưng endpoint khác lại trả:

{
  "success": true,
  "data": {
    "id": 456,
    "name": "Mouse"
  }
}

Nếu không có quy ước rõ ràng, frontend phải xử lý từng API theo một kiểu.

Một format nhất quán sẽ dễ sử dụng hơn.

Ví dụ:

{
  "data": {
    "id": 123,
    "name": "Laptop"
  }
}

Với danh sách:

{
  "data": [
    {
      "id": 123,
      "name": "Laptop"
    },
    {
      "id": 124,
      "name": "Mouse"
    }
  ]
}

Tuy nhiên, không có một response format duy nhất bắt buộc cho mọi REST API.

Điều quan trọng hơn là:

API đã chọn format nào thì nên giữ tính nhất quán giữa các endpoint.


4. Sử dụng HTTP Status Code thay vì nhét mọi thứ vào 200

Ví dụ request lấy user không tồn tại:

GET /users/999

Không nên luôn trả:

200 OK

với:

{
  "success": false,
  "message": "User not found"
}

Có thể sử dụng:

404 Not Found

Tương tự:

200 → Request thành công
201 → Resource được tạo
204 → Thành công nhưng không có response body
400 → Request không hợp lệ
401 → Chưa xác thực
403 → Đã xác thực nhưng không có quyền
404 → Không tìm thấy resource
409 → Conflict
500 → Lỗi phía server

Điều này giúp frontend có thể xử lý lỗi dựa trên HTTP semantics thay vì phải đọc message để đoán chuyện gì xảy ra.


5. API cần được thiết kế để có thể mở rộng

Một API ban đầu có thể chỉ có:

GET /products

Nhưng khi dữ liệu tăng lên hàng trăm nghìn sản phẩm, việc trả toàn bộ dữ liệu sẽ không còn hợp lý.

Ngay từ đầu có thể thiết kế:

GET /products?page=1&limit=20

Hoặc:

GET /products?page=2&limit=20&sort=name

Response:

{
  "data": [
    {
      "id": 101,
      "name": "Laptop"
    },
    {
      "id": 102,
      "name": "Mouse"
    }
  ],
  "pagination": {
    "page": 2,
    "limit": 20,
    "total": 150
  }
}

Tương tự, API thường sẽ cần:

Filtering
GET /products?category=electronics

Sorting
GET /products?sort=price

Searching
GET /products?search=laptop

Pagination
GET /products?page=1&limit=20

Nhờ vậy, API không cần tạo thêm hàng loạt endpoint như:

GET /getProductsByCategory
GET /searchProducts
GET /getProductsSortedByPrice

Thay vào đó, cùng một resource có thể được mở rộng bằng query parameters.


6. Một số nguyên tắc giúp API dễ maintain hơn

Đặt tên nhất quán

Nên chọn một convention:

/users
/products
/stock-transactions

và duy trì nó.

Tránh:

/users
/productList
/get-stock-transactions

Không đưa implementation detail vào URL

Ví dụ:

/users/getFromMongoDB

không phải một thiết kế tốt.

Client chỉ cần biết resource:

/users

Database phía sau là MongoDB, PostgreSQL hay Oracle không nên trở thành một phần của API contract.

Version API khi cần

Khi có breaking change:

/api/v1/users
/api/v2/users

Versioning giúp client cũ có thời gian chuyển sang API mới thay vì bị phá vỡ ngay lập tức.

Tuy nhiên, versioning không nên được thêm một cách máy móc cho mọi thay đổi nhỏ. Điều quan trọng là xác định rõ API contract và khi nào thay đổi được xem là breaking change.


7. Một ví dụ API chưa tốt và cách cải thiện

❌ Thiết kế khó mở rộng

POST /getProducts
POST /createProduct
POST /updateProduct
POST /deleteProduct
POST /searchProducts

✅ Thiết kế theo Resource

GET    /api/v1/products
POST   /api/v1/products
GET    /api/v1/products/123
PATCH  /api/v1/products/123
DELETE /api/v1/products/123

Tìm kiếm:

GET /api/v1/products?search=laptop

Phân trang:

GET /api/v1/products?page=1&limit=20

Lọc:

GET /api/v1/products?category=electronics

Khi nhìn vào API này, developer có thể nhanh chóng đoán được cách sử dụng mà không cần đọc tên từng function bên backend.


8. Những lỗi thường gặp khi thiết kế REST API

1. Dùng URL để mô tả action

POST /createUser
POST /deleteUser

→ Nên tận dụng HTTP Method.

2. Không nhất quán response

Endpoint trả:

{"data": ...}

endpoint khác lại trả:

{"result": ...}

→ Chọn một convention và duy trì.

3. Trả 200 OK cho mọi trường hợp

→ Sử dụng HTTP Status Code phù hợp.

4. Tạo quá nhiều endpoint

Ví dụ mỗi kiểu filter lại tạo một endpoint riêng.

→ Tận dụng query parameters khi phù hợp.

5. Không nghĩ đến pagination

GET /products

trả về hàng triệu record.

→ Thiết kế pagination ngay khi resource có khả năng tăng lớn.


Tóm lại

Một REST API tốt không phải là API có thật nhiều endpoint.

Hãy cố gắng đạt được 4 điều:

Resource rõ ràng
       ↓
HTTP Method đúng
       ↓
Response & Status Code nhất quán
       ↓
Có khả năng mở rộng

Mục tiêu cuối cùng là:

Developer mới nhìn vào API cũng có thể đoán được cách sử dụng mà không phải đọc toàn bộ source code backend.

Leave a Reply

Your email address will not be published. Required fields are marked *