+1

Làm chủ thiết kế API RESTful: Hướng dẫn thực tế

RESTful API (Representational State Transfer API) là một phong cách thiết kế giao diện mạng được sử dụng cho các tương tác giữa các ứng dụng mạng. REST là một tập hợp các nguyên tắc và ràng buộc về kiến ​​trúc chứ không phải là một tiêu chuẩn hoặc giao thức. Khi một dịch vụ web là "RESTful", nó tuân theo các nguyên tắc REST và cung cấp một dịch vụ mạng hiệu quả, đáng tin cậy và có thể mở rộng.

Trong dịch vụ RESTful, mỗi yêu cầu phải chứa tất cả thông tin cần thiết để xử lý yêu cầu. Máy chủ không được giữ lại bất kỳ thông tin trạng thái nào về yêu cầu của máy khách.

Kiến trúc RESTful có thể bao gồm nhiều lớp, mỗi lớp thực hiện một chức năng cụ thể. Cấu trúc này cho phép phát triển các ứng dụng phức tạp và mạnh mẽ hơn.

Thiết kế URI

Trong thiết kế RESTful API, URL (Uniform Resource Locators) thường biểu diễn tài nguyên (đối tượng), trong khi các phương thức HTTP (như GET, POST, PUT, DELETE, v.v.) biểu diễn các hoạt động trên các tài nguyên này (động từ). Phong cách thiết kế này nhấn mạnh vào trạng thái và biểu diễn tài nguyên hơn là hành động.

Động từ + Đối tượng

Động từ trong API RESTful thường là năm phương thức HTTP, tương ứng với các hoạt động CRUD:

  • GET: Read
  • POST: Create
  • PUT: Update
  • PATCH: Update (thường là update 1 phần)
  • DELETE: Delete

Theo đặc điểm kỹ thuật của HTTP, động từ phải luôn được viết hoa.

Đối tượng phải là một danh từ

Khi thiết kế API, URL (Uniform Resource Locator) thường biểu diễn một tài nguyên đóng vai trò là đối tượng của động từ HTTP. Theo nguyên tắc thiết kế RESTful, URL phải là danh từ chứ không phải động từ vì chúng biểu diễn một tập hợp "tài nguyên" hoặc một thể hiện duy nhất, không phải là một hành động.

Ví dụ không đúng: /getAllCars /createNewCar /deleteAllRedCars

Các URL này bao gồm các động từ (như get, create, delete), mô tả các hành động thay vì chính các tài nguyên. Thiết kế này không tuân thủ các tiêu chuẩn ngữ nghĩa RESTful.

Cách tiếp cận đúng:

URL nên tập trung vào việc mô tả tài nguyên hơn là hoạt động. Dưới đây là các ví dụ về thiết kế URL tuân thủ: /users: Biểu thị một tập hợp người dùng /users/123: Đại diện cho một người dùng duy nhất có ID cụ thể (123)

Trong các ví dụ trên, /users/users/123 đều là danh từ, lần lượt đại diện cho một tập hợp người dùng và một tài nguyên người dùng cụ thể. Thiết kế URL như vậy giúp API dễ hiểu hơn và phù hợp với các nguyên tắc hướng tài nguyên RESTful.

Bằng cách tuân theo quy ước đặt tên này, chúng tôi đảm bảo rằng các đường dẫn API rõ ràng, nhất quán, dễ hiểu và dễ bảo trì.

URL số nhiều

Việc sử dụng dạng số nhiều trong URL thường được khuyến khích vì tính nhất quán và rõ ràng, vì chúng thường biểu thị các tập hợp tài nguyên.

Khi URL của bạn trỏ đến một tập hợp các tài nguyên, hãy sử dụng danh từ số nhiều. Ví dụ, sử dụng /users thay cho /user để biểu diễn một tập hợp tất cả người dùng.

Ngay cả khi trỏ đến một tài nguyên duy nhất, nên sử dụng dạng số nhiều. Ví dụ, /users/123 biểu thị người dùng có ID 123. Cách tiếp cận này duy trì tính nhất quán của URL.

Khi tài nguyên có mối quan hệ phân cấp, URL phải phản ánh cấu trúc này. Ví dụ, /users/123/posts có thể biểu diễn tập hợp các bài đăng cho người dùng 123.

Tránh các URL lồng nhau sâu

Một kịch bản phổ biến là khi tài nguyên yêu cầu nhiều cấp độ phân loại, dẫn đến các URL lồng nhau sâu, chẳng hạn như truy xuất một danh mục bài viết nhất định của một tác giả cụ thể:

GET /authors/12/categories/2

Các URL như vậy khó mở rộng và ngữ nghĩa của chúng không rõ ràng, thường đòi hỏi nhiều nỗ lực hơn để hiểu. Một cách tiếp cận tốt hơn là sử dụng các tham số truy vấn ngoài cấp độ đầu tiên:

GET /authors/12?categories=2

Một ví dụ khác là truy vấn các bài viết đã xuất bản. Bạn có thể thiết kế URL như thế này:

GET /articles/published

Tuy nhiên, sử dụng tham số truy vấn rõ ràng là cách tiếp cận tốt hơn:

GET /articles?published=true

Mã trạng thái

Mã trạng thái phải chính xác

Đối với mỗi yêu cầu của khách hàng, máy chủ phải phản hồi bằng mã trạng thái HTTP và dữ liệu.

Mã trạng thái HTTP là một số gồm ba chữ số được chia thành năm loại:

  • 1xx : Information
  • 2xx : Success
  • 3xx : Redirection
  • 4xx : Client Errors
  • 5xx : Server Errors

Năm danh mục này chứa hơn 100 mã trạng thái bao gồm hầu hết các tình huống có thể xảy ra. Mỗi mã trạng thái có một ý nghĩa chuẩn (hoặc được chấp nhận theo thông lệ), cho phép máy khách xác định điều gì đã xảy ra chỉ bằng cách kiểm tra mã trạng thái. Do đó, máy chủ phải trả về mã trạng thái chính xác nhất có thể.

API không cần mã trạng thái 1xx . Dưới đây là giải thích về bốn loại khác.

Mã trạng thái 2xx

Các phương thức yêu cầu HTTP khác nhau sẽ trả về mã trạng thái tương ứng để chỉ ra kết quả yêu cầu. Trong khi 200 OK là phản hồi thành công chung, các mã trạng thái chính xác hơn sẽ được sử dụng tùy thuộc vào phương thức:

  • GET: 200 OK - Yêu cầu thành công và tài nguyên được trả về
  • POST: 201 Created - Một tài nguyên mới đã được tạo thành công và phản hồi thường bao gồm URI của tài nguyên đó.
  • PUT: 200 OK or 204 No Content - Được sử dụng để cập nhật toàn bộ tài nguyên. Nếu nội dung được trả về, hãy sử dụng 200 ; nếu không, hãy sử dụng 204 .
  • PATCH: 200 OK or 204 No Content - Được sử dụng cho các bản cập nhật một phần, tương tự như PUT. 204 biểu thị không có nội dung nào được trả về.
  • DELETE: 204 No Content - Chỉ ra rằng tài nguyên đã được xóa thành công, thường không có nội dung nào trong phản hồi.
  • 202 Accepted - Yêu cầu đã được chấp nhận nhưng chưa được xử lý, hữu ích cho các hoạt động không đồng bộ.
  • 206 Partial Content - Biểu thị phản hồi một phần, thường được sử dụng khi máy khách yêu cầu một phần của tệp lớn bằng cách sử dụng header Range.

Mã trạng thái 3xx

API thường không sử dụng 301 (Chuyển hướng vĩnh viễn) hoặc 302 (Chuyển hướng tạm thời, bao gồm 307) vì chúng chủ yếu liên quan đến điều hướng cấp trình duyệt. API có thể xử lý các tình huống như vậy ở cấp ứng dụng.

Tuy nhiên, API có thể sử dụng 303 See Other , tham chiếu đến một URL khác. Giống như 302 và 307 , nó có nghĩa là "chuyển hướng tạm thời", nhưng 303 được sử dụng cụ thể cho các yêu cầu POST, PUT và DELETE . Không giống như 302 , trình duyệt không tự động theo 303 chuyển hướng mà thay vào đó cho phép người dùng quyết định bước tiếp theo.

Ví dụ:

HTTP/1.1 303 See Other
Location: /api/orders/12345

Mã trạng thái 4xx

Mã trạng thái 4xx chỉ ra lỗi của máy khách. Các mã phổ biến bao gồm:

  • 400 Bad Request – Máy chủ không hiểu yêu cầu của máy khách và không xử lý yêu cầu đó.
  • 401 Unauthorized – Người dùng không cung cấp thông tin xác thực hoặc xác thực không thành công.
  • 403 Forbidden – Người dùng đã xác thực thành công nhưng không có quyền truy cập vào tài nguyên.
  • 404 Not Found – Tài nguyên được yêu cầu không tồn tại hoặc không khả dụng.
  • 405 Method Not Allowed – Người dùng đã xác thực thành công nhưng đang sử dụng phương pháp HTTP không được phép.
  • 410 Gone – Tài nguyên được yêu cầu đã bị xóa vĩnh viễn.
  • 415 Unsupported Media Type – Định dạng được yêu cầu không được hỗ trợ. Ví dụ: nếu API chỉ trả về JSON nhưng máy khách yêu cầu XML, trạng thái này sẽ được trả về.
  • 422 Unprocessable Entity – Khách hàng đã cung cấp tệp đính kèm không thể xử lý, dẫn đến yêu cầu không thành công.
  • 429 Too Many Requests – Máy khách đã vượt quá số lượng yêu cầu được phép.

Mã trạng thái 5xx

Mã trạng thái 5xx chỉ ra lỗi máy chủ. API thường không tiết lộ thông tin chi tiết về máy chủ nội bộ cho người dùng, do đó chỉ có hai mã trạng thái thường được sử dụng:

  • 500 Internal Server Error – Yêu cầu của khách hàng hợp lệ, nhưng máy chủ gặp sự cố không mong muốn khi xử lý yêu cầu đó.
  • 503 Service Unavailable – Máy chủ tạm thời không thể xử lý các yêu cầu, thường được sử dụng trong thời gian bảo trì.

Phản hồi của máy chủ

Không trả về văn bản thuần túy

Phản hồi API không nên là văn bản thuần túy mà là các đối tượng JSON có cấu trúc để đảm bảo định dạng chuẩn. Tiêu đề Content-Type của máy chủ phải được đặt thành application/json .

Máy khách cũng phải chỉ định rằng nó chấp nhận phản hồi JSON bằng cách đặt tiêu đề Accept trong yêu cầu của nó:

GET /orders/2 HTTP/1.1
Accept: application/json

Không trả về Mã trạng thái 200 cho Lỗi

Một cách tiếp cận không chính xác là luôn trả về 200 OK , ngay cả khi lỗi xảy ra và bao gồm chi tiết lỗi trong nội dung phản hồi. Điều này buộc máy khách phải phân tích nội dung phản hồi để xác định xem yêu cầu có thất bại hay không, làm suy yếu mục đích của mã trạng thái.

Ví dụ không tốt:

HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "failure",
  "data": {
    "error": "Expected at least two items in list."
  }
}

Trong trường hợp này, yêu cầu không thành công, nhưng máy chủ vẫn trả về 200 OK . Máy khách phải kiểm tra "status": "failure" trường trong nội dung phản hồi để phát hiện lỗi. Cách tiếp cận này không phải là RESTful và làm cho việc xử lý lỗi phức tạp hơn và dễ xảy ra lỗi hơn.

Ví dụ đúng: Mã trạng thái phải chỉ ra kết quả của yêu cầu. Lỗi phải được truyền đạt bằng cách sử dụng mã trạng thái thích hợp trong khi nội dung phản hồi cung cấp thêm chi tiết.

Ví dụ, nếu yêu cầu không hợp lệ, máy chủ sẽ trả về lỗi 400 Bad Request , kèm theo thông tin chi tiết về lỗi theo định dạng JSON:

HTTP/1.1 400 Bad Request
Content-Type: application/json
{
  "error": "Invalid payload.",
  "detail": {
    "surname": "This field is required."
  }
}

Ở đây, 400 rõ ràng chỉ ra yêu cầu không hợp lệ, trong khi nội dung phản hồi cung cấp thông tin chi tiết về lỗi để giúp khách hàng hiểu được vấn đề.

Cung cấp liên kết

Trong API RESTful, việc bao gồm các liên kết trong phản hồi là một thông lệ phổ biến. Điều này tuân theo nguyên tắc Hypermedia as the Engine of Application State (HATEOAS) , giúp tăng khả năng khám phá và tự mô tả API.

Sau đây là hai cách phổ biến để đưa liên kết vào:

Sử dụng HAL (Ngôn ngữ ứng dụng siêu văn bản)

HAL là một định dạng siêu phương tiện phổ biến biểu diễn mối quan hệ giữa các tài nguyên. Nó sử dụng trường _links trong phản hồi JSON:

{
  "id": 1,
  "name": "Example",
  "_links": {
    "self": {
      "href": "http://api.example.com/resource/1"
    },
    "related": {
      "href": "http://api.example.com/resource/2"
    }
  }
}

Nhúng liên kết trực tiếp vào JSON

{
  "id": 1,
  "name": "Example",
  "links": {
    "self": "http://api.example.com/resource/1",
    "related": "http://api.example.com/resource/2"
  }
}

Chính sách trả lại nội dung

Trong thiết kế RESTful API, các yêu cầu POST được sử dụng để tạo tài nguyên mới. Việc phản hồi có nên bao gồm tài nguyên mới được tạo hay không tùy thuộc vào nhu cầu triển khai. Có hai cách tiếp cận phổ biến:

1. Trả về tài nguyên đã tạo

Phương pháp này bao gồm mã trạng thái 201 Created và thông tin chi tiết đầy đủ về tài nguyên mới trong phản hồi. Nó cũng bao gồm tiêu đề Location trỏ đến URI của tài nguyên.

HTTP/1.1 201 Created
Location: /resources/123
Content-Type: application/json
{
  "id": 123,
  "name": "New Resource"
}

2. Không trả lại nội dung

Ngoài ra, máy chủ có thể chọn chỉ trả về phản hồi 201 Created hoặc 204 No Content với tiêu đề Location , bỏ qua chi tiết tài nguyên. Điều này giảm thiểu việc truyền dữ liệu và cho phép máy khách quyết định có truy xuất tài nguyên sau hay không.

HTTP/1.1 201 Created
Location: /resources/123

Kết luận

API RESTful tuân theo giao thức HTTP , nhấn mạnh vào biểu diễn tài nguyên và tương tác không trạng thái. Bằng cách sử dụng các phương thức HTTP chuẩn (GET, POST, PUT, DELETE) và mã trạng thái chính xác, kiến ​​trúc RESTful cung cấp một cách đơn giản, hiệu quả và dễ bảo trì để xây dựng các ứng dụng mạng. Cách tiếp cận này tăng cường khả năng mở rộng, tính linh hoạt và khả năng bảo trì cho các dịch vụ web.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.