Lập trình · 18/09/2026

Thiết kế REST API dễ hiểu, an toàn và dễ mở rộng

Hướng dẫn thiết kế REST API nhất quán và dễ mở rộng: resource, HTTP method, status code, phân trang, lỗi, versioning, bảo mật và tài liệu OpenAPI.

Thiết kế REST API dễ hiểu, an toàn và dễ mở rộng

Thiết kế REST API dễ hiểu, an toàn và dễ mở rộng

Một REST API tốt không chỉ trả về đúng dữ liệu. Nó còn phải dễ đoán với lập trình viên phía client, duy trì được tính tương thích khi sản phẩm thay đổi và cung cấp đủ tín hiệu để vận hành khi có sự cố.

Nhiều API bắt đầu rất đơn giản nhưng nhanh chóng trở nên khó dùng vì URL thiếu nhất quán, status code tùy tiện, lỗi không có cấu trúc hoặc thay đổi response làm hỏng ứng dụng cũ. Các nguyên tắc dưới đây giúp xây API như một hợp đồng lâu dài thay vì tập hợp endpoint rời rạc.

1. Thiết kế quanh resource, không quanh hành động

REST mô hình hóa tài nguyên. URI nên dùng danh từ và thể hiện quan hệ trong domain.

GET    /orders
POST   /orders
GET    /orders/123
PATCH  /orders/123
DELETE /orders/123

Tránh các đường dẫn như /getOrders hoặc /createOrder khi HTTP method đã mô tả hành động. Với nghiệp vụ không khớp CRUD, có thể mô hình hóa trạng thái hoặc sub-resource, ví dụ POST /orders/123/cancellations.

2. Dùng HTTP method đúng ngữ nghĩa

MethodMục đích phổ biếnTính chất
GETĐọc resourceSafe, idempotent
POSTTạo resource hoặc thực hiện commandThường không idempotent
PUTThay thế toàn bộ resource tại URI xác địnhIdempotent
PATCHCập nhật một phầnCần thiết kế cẩn thận
DELETEXóa resourceIdempotent về trạng thái cuối

Idempotent nghĩa là gửi cùng một request nhiều lần vẫn đưa hệ thống về cùng trạng thái. Thuộc tính này rất quan trọng khi client phải retry do timeout.

3. Trả status code có ý nghĩa

  • 200 OK: Request thành công và có response body.
  • 201 Created: Tạo resource thành công; nên trả URI của resource mới.
  • 202 Accepted: Đã nhận tác vụ bất đồng bộ nhưng chưa xử lý xong.
  • 204 No Content: Thành công nhưng không có body.
  • 400 Bad Request: Request không hợp lệ về cú pháp hoặc dữ liệu.
  • 401 Unauthorized: Chưa xác thực hợp lệ.
  • 403 Forbidden: Đã xác thực nhưng không có quyền.
  • 404 Not Found: Không tìm thấy resource.
  • 409 Conflict: Xung đột với trạng thái hiện tại.
  • 422 Unprocessable Content: Dữ liệu đúng cú pháp nhưng không qua validation nghiệp vụ.

Không nên trả 200 cho mọi tình huống rồi đặt lỗi trong body. Client, gateway và hệ thống giám sát đều dựa vào semantics của HTTP.

4. Chuẩn hóa response lỗi

Một lỗi tốt phải giúp client biết chuyện gì xảy ra, trường nào sai và có thể truy vết request nào trên hệ thống.

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Dữ liệu gửi lên chưa hợp lệ",
    "details": [
      {"field": "email", "reason": "invalid_format"}
    ],
    "trace_id": "req_01J..."
  }
}

code nên ổn định cho máy xử lý; message có thể dành cho con người. Không trả stack trace, câu SQL hoặc thông tin nội bộ ra môi trường production.

5. Phân trang, lọc và sắp xếp ngay từ đầu

Collection có thể tăng rất nhanh. Endpoint danh sách nên giới hạn kích thước response và có quy tắc nhất quán.

GET /orders?status=pending&sort=-created_at&limit=20&cursor=abc123

Offset pagination dễ triển khai, nhưng cursor pagination thường ổn định hơn với dữ liệu thay đổi liên tục. Response nên cung cấp metadata hoặc link để client biết cách lấy trang tiếp theo.

6. Xử lý tác vụ dài bằng mô hình bất đồng bộ

Nếu xuất báo cáo hoặc xử lý video mất nhiều thời gian, không giữ kết nối HTTP quá lâu. API có thể trả 202 Accepted cùng URL trạng thái.

POST /reports

HTTP/1.1 202 Accepted
Location: /operations/op_123

Client sau đó kiểm tra operation hoặc nhận webhook khi hoàn tất. Thiết kế này giảm timeout và giúp hệ thống mở rộng tốt hơn.

7. Giữ tương thích và có chiến lược versioning

API là hợp đồng với client. Thêm field thường ít rủi ro hơn đổi tên hoặc xóa field. Khi cần breaking change, hãy tạo phiên bản mới và duy trì phiên bản cũ trong một khoảng thời gian công bố rõ.

Version có thể nằm trong URL như /v2/orders, header hoặc media type. Quan trọng nhất không phải vị trí, mà là chính sách nhất quán về vòng đời, thông báo và ngày ngừng hỗ trợ.

8. Bảo mật theo nhiều lớp

  • Dùng HTTPS cho mọi môi trường có dữ liệu thật.
  • Xác thực bằng cơ chế chuẩn và kiểm tra quyền ở cấp resource.
  • Validate input theo allow-list và giới hạn kích thước payload.
  • Áp dụng rate limit theo người dùng, ứng dụng hoặc API key.
  • Không để ID khó đoán thay thế cho authorization.
  • Quản lý secret ngoài mã nguồn và luân chuyển định kỳ.
  • Ghi audit log cho hành động nhạy cảm.

9. Mô tả hợp đồng bằng OpenAPI

OpenAPI giúp tài liệu hóa endpoint, schema, parameter, response và cơ chế bảo mật theo định dạng máy đọc được. Từ hợp đồng này, đội ngũ có thể tạo tài liệu, client SDK, mock server và test tự động.

Contract-first đặc biệt hữu ích khi frontend và backend làm việc song song: hai bên thống nhất giao diện trước khi triển khai chi tiết.

10. Thiết kế cho khả năng quan sát

Mỗi request nên có correlation ID hoặc trace ID xuyên suốt gateway và các service. Theo dõi latency, error rate, throughput và dependency failure. Log cần đủ để điều tra nhưng không chứa token, mật khẩu hay dữ liệu cá nhân không cần thiết.

API dễ dùng thường là API có hành vi dễ đoán: cùng cách đặt tên, cùng cấu trúc lỗi, cùng quy tắc phân trang và cùng cách diễn giải HTTP.

Checklist trước khi phát hành API

  1. URI mô tả domain thay vì cấu trúc bảng dữ liệu.
  2. HTTP method và status code đúng semantics.
  3. Validation và lỗi có schema thống nhất.
  4. Collection có giới hạn, lọc, sắp xếp và phân trang.
  5. Request retry được bảo vệ bằng idempotency khi cần.
  6. Authentication, authorization và rate limit đã được kiểm thử.
  7. OpenAPI cập nhật cùng mã nguồn.
  8. Có log, metric, trace và cảnh báo vận hành.
  9. Breaking change có version và kế hoạch ngừng hỗ trợ.

Nguồn tham khảo

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.