Nếu bạn đã từng nghe rất nhiều lần về Restful API và cố gắng tìm hiểu nó nhưng khó có thể hiểu được cặn kẽ, hãy nghiên cứu series này và bạn có thể tìm ra một thứ gọi là chân lý. trong series này tôi sẽ chỉ cho bạn về tất tần tật các khái niệm theo cách dễ hiểu nhất và chia sẻ các kinh nghiệm, ví dụ khi thiết kế 1 Restful API.
Điều đầu tiên chúng ta cần hiểu Restful API là gì?
API (Application Programming Interface) là một cái gì đấy mà nó giống như khi bạn gọi ajax vậy, nó sẽ xử lý và trả về các kết quả qua JSON, XML… chứ k phải chỉ là html như các web thông thường.
Restful à một dạng chuyển đổi cấu trúc dữ liệu. Nó sử dụng phương thức HTTP. Thay vì sử dụng một URL để xử lý thì REST gửi một yêu cầu HTTP như GET, POST, DELETE, vv đến một URL để xử lý dữ liệu. đoạn này hơi khó nuốt
Hiểu đơn giản thì resful API là các chuẩn, các ràng buộc cho việc thiết kế. Bản chất nó là 1 chuẩn của thiết kế API cho web Service nên nó không quy định logic mà chỉ đơn giản là quy định cách sử dụng các phương thức (get, post, put, delete, put…) để truy cập và quản lý các resources.
Chú ý là chúng ta chỉ “nên” tuân theo nó, vậy thôi. ở đây t nhấn mạnh là “nên” tuân theo nó là bởi vì không phải lúc nào nó cũng hợp lý 100% với service của chúng ta (sẽ có các ví dụ ở phần sau).
Nó sự dụng HTTP và có 4 phương thức chủ yếu:
vậy nó trả về gì? ý mình ở đây là status của các request.
Đây là những kinh nghiệm mình đúc kết được khi làm về Restful
| route | get | post | put | delete |
|---|---|---|---|---|
| /users | return list users | create new user | update 1 list user | delete nhiều users |
| /users/1 | return profile of 1 user | nothing | update 1 user | delete 1 user |
1
GET https://api.example.com/posts?query[field]=title&query[compare]=like&query[value]=xzy
thế giả sử bạn phải search theo rất nhiều params thì có phải method get sẽ rất dài không, mà get chỉ đưa lên được một số giới hạn kí tự (có tài liệu ghi là 2048, 2047, lại có cái ghi rằng google SERP sẽ k xử lý các url dài hơn 1855 kí tự @@). vậy bạn filter quá nhiều thì chắc chắn là có thể dẫn đến tình trang tràn url. từ đó mà method get là tử thần (nó sinh ra mà bạn k đoán được), post lúc này lên ngôi và vô cùng hữu dụng vì nó truyền lên bao nhiêu cũng được.
vậy nên khi nào dùng get và post là do bạn quy đinh, hay tính đến các trường hợp mà bạn có thể nghĩ ra. đây chỉ là một ít kinh nghiệm của mìh thôi, rất mong các bạn dongds góp thêm
phần tìm kiếm thì nên đặt trong params có tên gợi nhắc (thường là q viết tắt của query). và bạn cũng nên xây dựng search theo global và scope riêng. cái này có thể không cần vì global search là đủ rồi, nhưng nó sẽ giúp ta hiểu dễ dàng hơn và k phải nối quá nhiều query vào cuối url
Phân trang hãy dùng page và limit để lấy. mình đã từng gặp một đội dev viết phân trang bằng cách sử dụng limit và offset(tương tư như page, tính bằng (page - 1)*number post of 1 page), nhưng điều đặc biệt là offset ở đây không phải là số thứ tự của id hay của bản ghi sau khi sắp xếp mà nó được lấy theo timestamp, do timestamp không phải duy nhất nên dẫn đến việc nó bị trùng và k phân trang đúng. (bạn tự giải thích tại sao lại k phân trang đúng nhé). do vậy mình đưa phần này và đây như một kinh nghiệm =))
tuỳ chọn field trả về phần này được nhắc đến như một phần tối quan trọng trong viẹc tối ưu hoá services. nếu bạn trả về quá nhiều thì rõ ràng là nó sẽ lâu, càng nhiều thì bên sử dụng sẽ càng load chậm. nếu thừa thì nó lại là phí phạm đường truyền. nên đôi lúc bạn nên quuêts định có nên trả về tất cả các field không hay chỉ trả về 1 phần của nó. trả về hết thì nhanh còn trả về 1 phần thì phải xem nó cần gì rồi mình trả về cái đó, mất thời gian làm hơn.
1
2
3
Content-type: application/json;charset=UTF-8
Content-Type: text/html; charset=UTF-8
Content-Type: multipart/form-data; boundary=something
Response format
1
2
Accept: application/json*
Accept: text/html
Chuẩn HTTP cung cấp hơn 70 status codes để mô tả các giá trị trả về. Dưới đây là một số status codes phổ biến hay dùng:
Trong đó: The client application behaved erroneously (client error - 4xx response code) The API behaved erroneously (server error - 5xx response code) The client must take some additional action. (redirection - 3xx response code) The client and API worked (success - 2xx response code)
Lỗi trả về nên rõ ràng cho dev phân tích và dễ hiểu cho user. ví dụ Value passed for name exceeded max length lúc này nên sửa dụng name_too_long thay vì invalid_name nhưng đừng nghĩ rằng nó đơn giản, hãy check ví dụ sau error establishing a database connection bên dev nên dùng nguyên nó còn hiển thị cho user nên sử dụng server error hoặc tương tự vì ng dùng có thể k hiểu database là gì.
XML không phải là một lựa chọn tốt cho API response. XML khá rườm rà, gây khó khăn khi đọc & phân tích cú pháp,… Tham khảo thêm tại đây, thay vào đó chúng ta sẽ sử dụng JSON. tuy nhiên SOAP lại là 1 chuẩn sử dụng xml và nó dùng cho các hệ thống lớn nên bạn k nên đánh giá nó mà nên tìm hiểu kĩ hơn. mình sẽ có bài phân tích lý do tại sao mà xml vẫn sánh vai trong các hệ thống thay vì sử dụng json. một số đạng response trả về mà mình từng sử dụng
1
2
3
4
5
6
7
8
9
10
{
"errors": [
{
"userMessage": "Sorry, resource does not exist",
"internalMessage": "No user found in the database",
"code": 34,
"more info": "http://example.com/api/v1/errors/12345"
}
]
}
1
2
3
4
5
6
{
"status": 400,
"message": "No user found in the database",
"code": 34,
"more info": "http://example.com/api/v1/errors/12345"
}
rồi giờ thì bạn thấy là nó có nhiều cách có thể làm được. nhưng sự khác nhau ở đây là gì?
ta dễ thấy là cách 2 sẽ k có bất kì phụ thuộc nào phía trước, đường dẫn là của chính nó. cách này sẽ có vấn đề gì?
vậy cách 1 thì sao?
rồi giờ thì chúng ta có thể thấy 1 loạt các ưu nhược điểm của 2 cách, giờ mix 2 cách với nhau chẳng phải là ổn rồi không. chúng ta sẽ đổi nó thành
1
2
3
4
5
6
7
8
users/1 -> lấy ra user
users/1/club -> lấy ra club
users/1/club/plans -> lấy ra plans
posts -> lấy ra posts
posts/1 -> lấy ra posts detail, update (PATCH, PUT), delete (DELETE)
posts/create -> tạo posts
posts/1/comment/create -> tạo comments
...
bây giờ thì ta sẽ thấy nó khá ổn cho một vài lần update, đường dẫn k quá dài. các phần như update 1 user sẽ có nhiều hơn 1 club ta vẫn sẽ để như vậy và sửa đường dẫn nhưng k phải sửa quá nhiều. phần comment và posts thì k có nhiều update nên có thể để như vậy là duy trì được trong thời gian rất dài phải không?
bài viết của mình đến đây là kết thúc rồi. hi vọng các bạn sẽ thích nó.
tham khảo: https://swagger.io/blog/api-design/api-design-best-practices/ https://www.oreilly.com/ideas/best-design-practices-to-get-the-most-out-of-your-api
Comments