blog.dopana

Back

API là cầu nối giữa frontend và backend. Một REST API được thiết kế tốt giúp frontend dễ dàng tích hợp, debug, và mở rộng.

1. Đặt Tên Endpoint#

Dùng Danh Từ Số Nhiều#

✅ GET    /users          # Danh sách user
✅ GET    /users/:id      # Chi tiết user
✅ POST   /users          # Tạo user
✅ PUT    /users/:id      # Cập nhật toàn bộ
✅ PATCH  /users/:id      # Cập nhật một phần
✅ DELETE /users/:id      # Xóa user

❌ GET    /getUsers       # Dùng động từ
❌ GET    /user           # Số ít
❌ POST   /createUser     # Lặp động từ
❌ DELETE /deleteUser?id=1 # Query param để xóa
txt

Resource Lồng Nhau#

GET    /users/:id/posts           # Bài viết của user
GET    /users/:id/posts/:postId   # Chi tiết bài viết
POST   /users/:id/posts           # Tạo bài viết cho user
txt

Actions — Khi CRUD Không Đủ#

POST   /users/:id/activate        # Kích hoạt user
POST   /orders/:id/cancel         # Hủy đơn hàng
POST   /posts/:id/like            # Thích bài viết
txt

Dùng POST thay vì GET/DELETE cho action — không phải action nào cũng là CRUD.

2. Versioning#

URL Path (Phổ biến nhất)#

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

Header (Less intrusive)#

Accept: application/vnd.myapp.v1+json
txt

URL path dễ đọc, dễ test, dễ route. Header “sạch” hơn về mặt REST thuần túy.

3. Response Format — Consistency Là Chìa Khóa#

Pagination#

GET /users?page=1&limit=20

{
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 150,
    "totalPages": 8,
    "hasNext": true,
    "hasPrev": false
  }
}
json

Dùng cursor-based pagination cho real-time data (chat, feed):

GET /messages?cursor=eyJpZCI6MTB9&limit=20

{
  "data": [...],
  "nextCursor": "eyJpZCI6MzB9"
}
json

4. HTTP Status Code — Dùng Đúng Mã#

CodeÝ nghĩaDùng khi
200OKThành công
201CreatedPOST tạo resource
204No ContentDELETE thành công
400Bad RequestValidation lỗi
401UnauthorizedChưa đăng nhập
403ForbiddenKhông có quyền
404Not FoundResource không tồn tại
409ConflictTrùng lặp, xung đột
422Unprocessable EntityDữ liệu không hợp lệ
429Too Many RequestsRate limit
500Internal Server ErrorLỗi server

5. Filtering, Sorting, Searching#

# Filtering
GET /users?role=admin&status=active

# Sorting
GET /users?sort=name,-createdAt # name ASC, createdAt DESC

# Searching
GET /users?search=alice

# Field selection
GET /users?fields=id,name,email
bash

6. Authentication#

JWT trong Header#

Authorization: Bearer <token>
http

Trừ khi bạn cần bảo vệ khỏi XSS (httpOnly cookie). Cân nhắc:

  • Bearer token — Đơn giản, mobile-friendly
  • httpOnly cookie — Chống XSS, nhưng dễ bị CSRF
  • Both — Access token (short-lived) + Refresh token (httpOnly)

7. Rate Limiting — Trả Về Header#

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1718845200
http

8. Idempotency — An Toàn Khi Retry#

POST /payments
Idempotency-Key: uuid-v4
http

Server dùng key này để detect request trùng:

const existing = await cache.get(idempotencyKey);
if (existing) return existing;

const result = await processPayment(data);
await cache.set(idempotencyKey, result, { ttl: 86400 });
return result;
typescript

Cực kỳ quan trọng cho payment, order — nơi retry có thể gây hậu quả nghiêm trọng.

9. API Documentation#

Công cụ phổ biến cho API documentation:

  • OpenAPI/Swagger — Tiêu chuẩn, sinh từ code
  • Scalar — Giao diện đẹp, hiện đại
  • Stoplight — Design-first API

Kết Luận#

REST API design không có “đúng tuyệt đối” — nhưng có những convention giúp API của bạn dễ dùng, dễ mở rộng. Quan trọng nhất: be consistent. Chọn một style và giữ nó xuyên suốt toàn bộ API.

Tài liệu tham khảo#