+3

Một số tips để thiết kế APIs hiệu quả

Xây dựng một API phong phú và chuyên nghiệp không phải là khó, nhưng có rất nhiều điều bạn nên xem xét ngay từ đầu. Dưới đây là một số khái niệm quan trọng nhất và thực hành tốt nhất mà tôi học được trong khi xây dựng API với Rails.

Sử dụng versioning

350-rest-api-versioning.png

Ngay cả khi bạn chỉ mới bắt đầu phát triển sản phẩm của bạn và không chắc chắn là sau này sẽ có cơ hội để tạo ra những phiên bản tiếp theo của API, thì bạn cũng nên tạo một version cho nó. Sẽ tốn rất ít công sức và cũng dễ dàng hơn rất nhiều để thêm những phiên bản mới khi sản phẩm của bạn đi tới thành công. Nếu bạn có một sản phẩm thành công, bạn hầu như sẽ luôn phải điều chính API của bạn và do đó sẽ cần phải phát hành một phiên bản v2 cho API đó.

Trong Rails, để định nghĩa các phiên bản khác nhau, chúng ta khai báo một namespace đơn giản trong routes như sau:

namespace :api do
  namespace :v1 do
    resources :projects
  end
end

Khi đó, đường dẫn đến API trông sẽ dễ đọc như này: api/v1/projects

Tôi khuyến khích bạn nên cài đặt phiên bản của API như là một phần của URL, vì đây là phương pháp rõ ràng, minh bạch nhất đối với người dùng.

Sử dụng HTTP Status Codes đúng

HTTP cung cấp cho bạn một cơ chế tuyệt vời để thông báo cho những người dùng API của bạn nếu như request là thành công hay không: HTTP status codes

Sử dụng các status codes đó đúng sẽ cung cấp cho người dùng những thông tin hữu dụng. Họ sẽ cảm ơn bạn ^ ^. Bảng dưới đây là một số HTTP status codes điển hình của REST-API:

Code Tên Ý nghĩa
200 OK Mọi thứ diễn ra đều tốt. Tôi trả lại tài nguyên bạn đã yêu cầu
201 Created Chúng tôi đã tạo thành công một tài nguyên cho bạn
204 No Content Tôi đã xử lý thành công yêu cầu của bạn và không trả về bất cứ nội dung nào
401 Unauthorized Bạn đã không cung cấp thông tin xác thực hợp lệ
404 Not found Tài nguyên bạn yêu cầu không thể tìm thấy nhưng có thể sẽ có trong tương lai
422 Unprocessable Entity Tài nguyên không thể lưu trữ. Có thể đã xảy ra lỗi xác thực

Rails controller làm cho API của bạn thực sự thuận tiện để sử dụng đúng các status codes, như sau:

render json: @object, status: :created

Sử dụng đúng HTTP verbs

Bên cạnh những HTTP status codes vô cùng hữu ích, bạn cũng nên sử dụng đúng HTTP verbs. Phổ biến nhất mà bạn cần trong bất kỳ REST-API nào là:

Verb Cách dùng
GET Chỉ lấy về dữ liệu. Không bao giờ thay đổi bất kì dữ liệu nào với một GET request
POST Tạo mới một tài nguyên
PUT/PATCH Cập nhật một tài nguyên đang tồn tại trong hệ thống
DELETE Xóa một tài nguyên

Sử dụng những HTTP verbs đó đúng cách để hướng dẫn người dùng sử dụng đúng API của bạn. Routing method của Rails giúp cho bạn thực hiện đúng các HTTP verbs cho các action của bạn một cách dễ dàng. Xem Rails guide on routing để biết thêm chi tiết.

Trả về error message đúng

Xử lý lỗi trong một API nghe có vẻ dễ dàng nhưng đòi hỏi bạn cần có một kế hoạch cẩn thận. Khuyến khích luôn luôn trả về những error messages trong các định dạng tương tự mà người dùng không cần phải xử lý các ngữ nghĩa khác nhau đối với những tài nguyên khác nhau. Ngoài ra, hãy xem xét một số ngôn ngữ client có thể không hỗ trợ việc nested tùy ý trong JSON response và do đó sẽ gặp một vài rắc rối đối với việc phân tích nó.

Sử dụng HTTP status code ở trên đầu mỗi eror message.

Nếu bạn muốn đi xa hơn nữa, bạn có thể thêm vào một đường dẫn đến bài viết từ document của bạn khi có lỗi xảy ra để người dùng có thể debug vấn đề ngay lập tức. Không có gì tệ hơn là một lỗi không có hoặc thậm chí là có một error message sai. Luôn luôn cố gắng làm những gì có ích đối với người dùng của bạn nhất có thể.

Một error message response tốt có thể trông như sau:

Status: 422

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Project",
      "field": "name",
      "message": "can't be blank"
    }
  ]

Luôn luôn phân trang cho kết quả của bạn

Hãy thử tưởng tượng, một request có tới hàng trăm nghìn cho tới hàng triệu bản ghi được trả về cùng một lúc, điều này dẫn dến sự bất tiện nghiêm trọng đối với database, browser cũng như web-server của bạn. Vì vậy cách tốt nhất để tránh được điều này là bạn nên phân trang cho những kết quả được trả về theo một list.

Phân trang trong Rails có thể dễ dàng được thực hiện bằng cách sử dụng gem như kaminari, nhưng bạn cũng có thể thực hiện nó bằng cách sử dụng LIMITOFFSET trong câu truy vấn của bạn.

Khi trả lại kết quả phân trang của bạn, hãy chắc chắn rằng bạn sẽ hiển thị thông tin meta phân trang cho người sử dụng. Tôi đã tìm thấy một cách rất tốt để làm việc này thông qua HTTP Link-Headers trong response.

Header chứa đầy đủ URL đến next, previous, firstlast page của kết quả trả về và làm cho nó thực sự dễ dàng để client có thể xử lý kết quả phân trang của bạn.

Link: <https://domain.com/api/v2/projects?page=1>; rel="first", <https://domain.com/api/v2/projects?page=3>; rel="prev", <https://domain.com/api/v2/projects?page=5>; rel="next", <https://domain.com/api/v2/projects?page=9>; rel="last"

Xác thực

Nếu bạn đang xây dựng một private API, điều bạn cần phải làm là xây dựng cơ chế xác thực cho nó. Một số cơ chế xác thực hay được sử dụng như HTTP Basic Authentication và HTTP Digest Authentication : http://guides.rubyonrails.org/action_controller_overview.html#http-authentications. Những cách này khá dễ dàng để thực hiện. Bên cạnh cơ chế xác thực dễ dàng đó, bạn cũng nên cho phép người dùng đăng nhập bằng cách sử dụng một private access tokens. Cách này được khuyên dùng khi bạn xử lý việc truy cập từ private resource của bạn tới một vài external service.

Rate Limiting

RateLimiting.gif

Khi người dùng bắt đầu sử dụng API của bạn, bạn có thể không phải lo lắng về hiệu suất hoặc giới hạn tài nguyên của bạn.Tuy nhiên, nếu ứng dụng của bạn thành công và có đến hàng nghìn người dùng bắt đầu tích hợp API vào cơ sở hạ tầng và quy trình làm việc của họ, mọi thứ có thể sẽ đi sai hướng. Vì vậy, để tránh lạm dụng, thì bạn nên xem xét việc thêm rate-limiting vào API của bạn.

Ví dụ, bạn có thể muốn giới hạn việc sử dụng API của mỗi người dùng được nhiều nhất là 100 lần gọi API trong khoảng thời gian là 10 phút. Nếu có quá nhiều request được nhận từ một người dùng trong một khoảng thời gian nhất định, một response với status code là 429 (Có nghĩa là "Có quá nhiều request") nên được trả về.

Khi rate limiting được enabled, mặc định mọi response sẽ được gửi đi kèm với HTTP headers có chứa những thông tin rate limiting hiện tại:

  • X-Rate-Limit-Limit, số tối đa request được cho phép với mỗi khoảng thời gian
  • X-Rate-Limit-Remaining, số request còn lại trong khoảng thời gian hiện tại
  • X-Rate-Limit-Reset, số giây chờ đợi để lấy được tối đa số request cho phép

HTTP Caching: Conditional GET

http-cache-control-highlight.png

Với bất kì web service thành công nào, caching trở nên rất quan trọng để đảm bảo cho hiệu suất đạt hiệu quả của hệ thống. HTTP đi cùng với cơ chế caching khá là dễ dàng để sử dụng trong Rails.

Học thêm về HTTP caching trong Rails: Conditional GET

Các phương pháp cần xem xét là self-invalidating cache keys, Russian Doll Caching, và Reverse-Proxy-Caches (Varnish, CDNs).

Document tất tần tật

1-g72iSukKuZONgs1Ou_GpOw.jpeg

Công việc document vô cùng nhàm chán, và như bao thứ nhàm chán khác, lại rất cần thiết. Một chương trình với document tốt sẽ cứu rỗi tinh thần của bạn. Bạn sẽ giảm bớt lượng câu hỏi khồng lồ của người dùng về API của bạn, vì dù gì thì “thời gian là vàng bạc” mà.

Document tốt cần có:

  • Tổng quan chi tiết và cách làm việc của module
  • Javadocs, Heredocs, Rdocs hoặc bất cứ thông tin gì về public method và protocols.
  • Code mẫu thể hiện cách sử dụng.

Không phải tất cả cái gì trừu tượng đều yêu cầu cùng một mức document như nhau. Ví dụ như, một class be bé cũng chả cần code mẫu làm gì.

Documentation cần được làm mới liên tục. Nếu bạn nhận được nhiều câu hỏi về cùng hỏi một thứ, bạn có thể thêm vào doc để giải thích cho người dùng mới.

Quá nhiều document cũng sẽ lãng phí thời gian. Và có nhiều phần vô dụng vì chả ai dùng đến cả. Hãy thật sự document những gì hữu ích.

Kết luận

Thiết kế API là cả một nghệ thuật. Hi vọng bài viết trên đây sẽ giúp bạn thiết kế được một API tốt cho bản thân mình. (yeah)

Nguồn tham khảo

  1. https://phraseapp.com/blog/posts/best-practice-10-design-tips-for-apis/

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí