Restful Web Service là gì?
1. RESTful Service là gì? Những khái niệm đầu tiên về REST ( Representational State Transfer) được đưa ra vào năm 2000 trong luận văn tiến sĩ của Roy Thomas Fielding (đồng sáng lập giao thức HTTP). Trong luận văn ông giới thiệu khá chi tiết về các ràng buộc, quy ước cũng như cách thức thực hiện ...
1. RESTful Service là gì?
Những khái niệm đầu tiên về REST ( Representational State Transfer) được đưa ra vào năm 2000 trong luận văn tiến sĩ của Roy Thomas Fielding (đồng sáng lập giao thức HTTP). Trong luận văn ông giới thiệu khá chi tiết về các ràng buộc, quy ước cũng như cách thức thực hiện với hệ thống để có được một hệ thống REST.
REST định nghĩa các quy tắc kiến trúc để bạn thiết kế Web Services, chú trọng vào tài nguyên hệ thống, bao gồm các trạng thái tài nguyên được định dạng như thế nào và được truyền tải qua HTTP, và được viết bởi nhiều ngôn ngữ khác nhau. Nếu tính theo số dịch vụ mạng sử dụng, REST đã nổi lên trong vài năm qua như là một mô hình thiết kế dịch vụ chiếm ưu thế. Trong thực tế, RESTđã có những ảnh hưởng lớn và gần như thay thế SOAP và WSDL vì nó đơn giản và dễ sử dụng hơn rất nhiều.
REST là một bộ quy tắc để tạo ra một ứng dụng Web Service, mà nó tuân thủ 4 nguyên tắc thiết kế cơ bản sau:
- Sử dụng các phương thức/hành động HTTP một cách rõ ràng
- Phi trạng thái
- Hiển thị cấu trúc thư mục như các URls
- Truyền tải JSON, XML hoặc cả hai.
- Và một số nguyên tắc tối giản khác
2. Nên sử dụng các phương thức/hành động HTTP một cách rõ ràng
REST đặt ra một quy tắc đòi hỏi lập trình viên xác định rõ ý định của mình thông qua các phương thức của HTTP. Thông thường ý định đó bao gồm lấy dữ liệu, thêm dữ liệu, chỉnh sửa hoặc xóa dữ liệu. Vậy khi bạn muốn thực hiện một trong các ý định trên hãy lưu ý những hành động CRUD sử dụng những phương thức HTTP sau:
- GET (SELECT): Trả về một Resource hoặc một danh sách Resource.
- POST (CREATE): Tạo mới một Resource.
- PUT (UPDATE): Cập nhật thông tin cho Resource.
- PATCH (UPDATE): Cập nhật một thành phần, thuộc tính của Resouce.
- DELETE (DELETE): Xoá một Resource.
- HEAD – Trả về thông tin chung của một hoặc danh sách Resource.
- OPTIONS – Trả về thông tin mà người dùng được phép với Resource
Chú ý: Các hành động ở trên là không bắt buộc, thực tế bạn có thể sử dụng phương thức GET để yêu cầu lấy dữ liệu, thêm, sửa hoặc xóa dữ liệu trên Server-side. Tuy nhiên REST đưa ra các nguyên tắc hành động ở trên mục đích đưa mọi thứ trở lên rõ ràng và dễ hiểu.
Ví dụ sau đây là cách bạn sử dụng GET để yêu cầu thêm dữ liệu trên Server-side(Chú ý, đây là cách trái với nguyên tắc của REST).
Sử dụng GET để yêu cầu thêm một ticket có tên là "A"
GET /tickets/add?name=A HTTP/1.1
Sử dụng GET để yêu cầu Server đổi tên ticket có tên A thành B.
GET /tickets/update?name=A&newname=B HTTP/1.1
Và bây giờ theo các quy tắc của REST mọi thứ trở lên rõ ràng hơn.
Gửi lệnh HTTP POST để thêm dữ liệu:
POST /tickets/add/A HTTP/1.1 Host: api.example.com Content-Type: application/xml <?xml version="1.0"?> <ticket> <name>A</name> </ticket>
Gửi một lệnh GET nếu bạn muốn lấy dữ liệu trên hệ thống.
GET /tickets/getOneTicket/A HTTP/1.1 Host: api.example.com Accept: application/xml
Gửi một lệnh PUT nếu bạn muốn cập nhập dữ liệu.
PUT /tickets/update/A HTTP/1.1 Host: api.example.com Content-Type: application/xml <?xml version="1.0"?> <ticket> <name>B</name> </ticket>
Gửi lệnh DELETE nếu bạn muốn xóa dữ liệu:
DELETE /tickets/delete/1 HTTP/1.1
3. Phi trạng thái (Stateless)
Một đặc điểm của REST là phi trạng thái (Stateless), có nghĩa là nó không lưu giữ thông tin của Client. Chẳng hạn bạn vừa gửi yêu cầu để xem trang thứ 2 của một tài liệu, và bây giờ bạn muốn xem trang tiếp theo (sẽ là trang 3). REST không lưu trữ lại thông tin rằng trước đó nó đã phục vụ bạn trang số 2. Điều đó có nghĩa là REST không quản lý phiên làm việc (Session).
Hình dưới đây minh họa một ứng dụng có lưu trữ trạng thái, nó biết người dùng đang xem trang số mấy. Và người dùng chỉ cần yêu cầu "Trang Tiếp theo" để nhận được trang mong muốn.
Với các thiết kế phi trạng thái, Client phải gửi yêu cầu rõ ràng, bao gồm số thự tự của trang cần xem.
Như vậy, các thành phần máy chủ phi trạng thái ít phức tạp hơn để thiết kế, viết và phân bổ thông qua máy chủ được cân bằng tải. Dịch vụ phi trạng thái không chỉ hoạt động tốt hơn, nó còn chuyển hầu hết vai trò duy trì trạng thái sang ứng dụng ở máy khách. Trong một dịch vụ mạng RESTful, máy chủ chịu trách nhiệm đưa ra các phản hồi và cung cấp một cách thức cho phép Client duy trì trạng thái ứng dụng của chính nó.
4. Đưa ra cấu trúc thư mục giống các URI
REST đưa ra một cấu trúc để người dùng có thể truy cập vào tài nguyên của nó thông qua các URL, tài nguyên ở đây là tất cả những cái mà bạn có thể gọi tên được (Video, ảnh, báo cáo thời tiết,..)
Bạn cần tạo ra các REST serivce để nó trả về cho người dùng các nguồn tài nguyên tương ứng.
Các địa chỉ REST service cần phải thật trực quan đến mức người dùng dễ đoán. Hãy nghĩ về một địa chỉ (URI) giống như một gợi ý rõ ràng, dễ đoán rằng nó đang trỏ tới cái gì và cung cấp tài nguyên gì. Tóm lại, cấu trúc của một URI nên được đơn giản, có thể dự đoán, và dễ hiểu.
Hãy xem một URL dưới đây, nó cung cấp thông tin thời tiết của một khu vực ứng với một ngày cụ thể, và nó dễ hiểu đối với người dùng.
http://myservice.com/weather/chicago/2016-09-27 // Hoặc http://myservice.com/weather/hanoi/2016-11-11
Một vài nguyên tắc bổ sung để lưu ý trong khi nói về cấu trúc địa chỉ của RESTful Web Service là:
- Giấu các đuôi file mở rộng của bản gốc trong máy chủ (.jsp, .php, .asp). Vì thế bạn có thể giấu mọi thứ mà không thay đổi URLs.
- Để mọi thứ là chữ thường.
- Thay thế các khoảng trống bằng gạch chân hoặc hoặc gạch nối (một trong hai loại).
- Tránh các chuỗi yêu cầu càng nhiều càng tốt.
- Thay vì sử dụng mã (404 Not Found) khi yêu cầu địa chỉ cho một phần đường dẫn cụ thể, luôn luôn cung cấp một trang hay một tài nguyên mặc định như một phản hồi.
6. Truyền tải XML, JSON hoặc cả hai
Khi Client gửi một yêu cầu(request) tới Web Service nó thường được truyền tải dưới dạng XML hoặc JSON và thông thường nhận về với hình thức tương tự.
Đôi khi Client cũng có thể chỉ định kiểu dữ liệu nhận về mà nó mong muốn (JSON, hoặc XML,..), các chỉ định này được gọi là các kiểu MINE, nó được gửi kèm trên phần HEADER của yêu cầu (request). Dưới đây là các kiểu MINE phổ biến thường sử dụng với RESTful Web Service.
MIME-Type | Content-Type |
---|---|
JSON | application/json |
XML | application/xml |
XHTML | application/xhtml+xml |
Ví dụ Client gửi một yêu cầu để lấy thông tin thời tiết, và yêu cầu dữ liệu trả về là định dạng XML.
GET /weather/chicago/2016-08-27 HTTP/1.1 Host: api.example.com Accept: application/xml;q=0.5
Và dữ liệu nhận được:
<weather> <date>2016-08-27</date> <location>Chicago</location> <info>Hot</info>"// </weather>
Trường hợp client yêu cầu dữ liệu trả về có định dạng JSON:
{ "date": "2016-08-27", "location": "Chicago", "info": "Hot" }
7. Sử dụng danh từ số nhiều, không dùng động từ
Danh từ số nhiều: Mặc dù là sẽ có những ngữ cảnh mô tả một trường hợp trong những Resource nhưng trong thực tế để giữ cho định dạng URL nhất quán thì sẽ nên luôn luôn sử dụng số nhiều. Không phải đối phó với những danh từ (person/people, goose/geese) sẽ làm những người sử dụng API thấy dễ chịu hơn và cũng sẽ cho bên cung cấp API dễ thực thi nó (/tickets và tickets/12 thường được viết trong một controller chung)
- GET /tickets – Trả về danh sách những ticket
- GET /tickets/12 – Trả về một ticket được định danh
- POST /tickets – Tạo mới một ticket
- PUT /tickets/12 – Cập nhật thông tin cho ticket #12
- PATCH /tickets/12 – Cập nhật một thuộc tính cho ticket #12
- DELETE /tickets/12 – Xóa ticket #12
Nếu tồn tại một quan hệ duy nhất với Resource khác, RESTful cung cấp những hướng dẫn có ích.
Ví dụ:
- GET /tickets/12/messages – Trả về danh sách message của ticket #12
- GET /tickets/12/messages/5 – Trả về message #5 của ticket #12
- POST /tickets/12/messages – Tạo mới một message trong ticket #12
- PUT /tickets/12/messages/5 – Cập nhật message #5 của ticket #12
- PATCH /tickets/12/messages/5 – Cập nhật một số thuộc tính của message #5 cho ticket #12
- DELETE /tickets/12/messages/5 – Xoá message #5 for ticket #12
Không nên sử dụng động từ:
- GET /getAllCars
- POST /createNewCar
- DELETE /deleteAllRedCars
8. Authentication
RESTfull API không sử dụng session à cookie, bởi vậy nên sử dụng một mã bí mật access_token với mỗi request. Luôn sử dụng SSL
https://api.example.com/users?access_token=1qaz3edc...
9. Pretty print và gzip cần được hỗ trợ
Một API mà những khoảng trắng, ký tự space đã được nén lại thì thật không vui khi mà phải quan sát từ Browser. Và khi sử dụng Gzip có thể giúp tiết kiệm đến 60% băng thông.
10. Version
Hãy luôn sử dụng version trong API của bạn. Version sẽ giúp bạn lặp lại nhanh hơn và ngăn ngừa được những request không hợp lệ. Nó cũng sẽ giúp bạn suôn sẻ dễ dàng khi chuyên đổi những version API hay như là bạn có thể tiếp tục cung cấp các những version cũ trong một khoảng thời gian.
- https://example.org/api/v1/*
- https://api.example.com/v1/*
Nếu ứng dụng của bạn lớn, sự lựa chọn tốt nhất nên đặt API ở subdomain e.g https://api.example.com. Nó có thể giúp làm giảm được sự tải trang.
11. Những mã HTTP thường được sử dụng
- 200 OK – Trả về thành công cho những phương thức GET, PUT, PATCH hoặc DELETE.
- 201 Created – Trả về khi một Resouce vừa được tạo thành công.
- 204 No Content – Trả về khi Resource xoá thành công.
- 304 Not Modified – Client có thể sử dụng dữ liệu cache.
- 400 Bad Request – Request không hợp lệ
- 401 Unauthorized – Request cần có sự authentication.
- 403 Forbidden – Server hiểu request nhưng bị từ chối không cho phép.
- 404 Not Found – Không tìm thấy rource từ URI
- 405 Method Not Allowed – Phương thức không cho phép với user hiện tại.
- 410 Gone – Resource không còn tồn tại, Version cũ đã không còn hỗ trợ.
- 415 Unsupported Media Type
- 422 Unprocessable Entity – Dữ liệu không được kiểm chứng
- 429 Too Many Requests – Request bị từ chối do bị giới hạn
12. Caching
Có 2 phương pháp nên được áp dụng là Etag và Last-Moified.
13. Lỗi
Có những lúc bạn muốn tuỳ biến định dạng lỗi mặc định được trả về, ví dụ như sử dụng những trạng thái, mã HTTP khác để chỉ ra những lỗi khác nữa, một lời khuyên bạn nên luôn sử dụng mã 200 và những mã lỗi thực sẽ là một thành phần của cấu trúc JSON được trả về giống như là sau:
14. Return Data(Dữ liệu trả về)
Dữ liệu trả về nhiều khi bao bọc trong một số trường hợp là không thật sự cần thiết theo CORS và Link header from RFC 5988. Một vài REST Client không cho phép truy cập tới HTTP Header và cũng như JSONP không có quyền truy cập vậy, do vậy có thể bao bọc dữ liệu trả về trong những trường hợp cần thiết.
15. Tổng kết.
Một API như là một User Interface cho những người phát triển. Hãy cố gắng để đảm bảo nó không chỉ là chức năng mà còn làm người sử dụng thấy dễ dàng khi sử dụng. Để thiết kế một API tốt thật sự là một điều rất khó. Tài liệu thiết kế API rất quan trọng nhưng cũng thật khó để tìm ra một lập trình viên thích viết tài liệu mô tả cho nó.
16. Tham khảo.
[1] https://codeplanet.io/principles-good-restful-api-design/ [2] http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api