Mình đã hướng dẫn các bạn cách định nghĩa RESTful Web Service API specs sử dụng RAML. Có một cách khác để làm điều này là sử dụng OpenAPI Specification. Cụ thể như thế nào? Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu làm thế nào để định nghĩa RESTful Web Service API specs sử dụng OpenAPI Specification các bạn nhé!
Chúng ta sẽ sử dụng tập tin YAML hoặc JSON để định nghĩa API specs với OpenAPI Specification. Dưới đây là nội dung tập tin YAML định nghĩa API specs trong bài viết Giới thiệu về RAML sử dụng OpenAPI Specification:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
openapi: 3.0.3 info: title: Student Information Management System version: 1.0.0 servers: - url: https://localhost:8081/api paths: /students: get: operationId: getStudents summary: Get all students responses: 200: description: Get all students successfully content: application/json: example: [{ "id": 1, "code": "001", "name": "Khanh" }, { "id": 2, "code": "002", "name": "Quan" }] /students/{id}: get: operationId: getStudentById summary: Get a student by id parameters: - name: id in: path description: "Id of the Student" required: true schema: type: string responses: 200: description: Get student information successfully content: application/json: example: { "id": 1, "code": "001", "name": "Khanh" } delete: operationId: deleteStudentById summary: Delete a student by id parameters: - name: id in: path description: "Id of the Student" required: true schema: type: string responses: 200: description: Delete student information successfully content: application/json: example: { "message": "Student deleted!"} |
Như các bạn thấy, tương tự như định nghĩa API specs với RAML, ở đầu tập tin YAML này, chúng ta sẽ định nghĩa một số thông tin overview về API specs của mình. Chúng ta sử dụng field openapi để định nghĩa OpenAPI Specification version chúng ta sẽ sử dụng để định nghĩa API specs, thông tin về API specs bao gồm mục đích của nó (field info.title), version của API specs này (info.version). Base URL sẽ được định nghĩa sử dụng field servers.url.
Các request URL sẽ được định nghĩa với section paths.
Chúng ta không định nghĩa các request URL với giá trị bắt đầu giống nhau theo kiểu extends như bên RAML được. Chúng ta chỉ có thể gom các request có HTTP method khác nhau nhưng cùng một request URL. Trong ví dụ trên thì request URL “/students/{id}” được định nghĩa với GET và DELETE method, chúng ta có thể gom 2 request URL này lại với nhau.
Chúng ta có thể sử dụng field operationId để identify cho mỗi request URL. Giá trị của field này là duy nhất trong 1 API specs cho mỗi request URL.
Tương tự như RAML, chúng ta cũng có thể định nghĩa response cho mỗi response status code, mỗi response có thể có kiểu dữ liệu khác nhau. Trong ví dụ của mình thì đó là application/json.
Để định nghĩa parameter cho các request URL, chúng ta sẽ sử dụng section parameters trong mỗi request. Các parameter có thể là path parameter, query parameter hay nằm trong header, cookie. Chúng ta sử dụng field in của mỗi parameter để khai báo điều này.
OpenAPI cũng hỗ trợ nhiều kiểu dữ liệu khác nhau như RAML. Các bạn có thể tham khảo thêm ở đây các bạn nhé! Ở ví dụ trên, chúng ta có thể định kiểu dữ liệu của response body cho các request URL với Schema object bằng cách khai báo section components.schemas như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
components: schemas: Student: type: object properties: id: type: integer format: int64 code: type: string name: type: string Response: type: object properties: message: type: string |
sau đó thì khai báo các Schema object này trong phần response body của mỗi request như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
openapi: 3.0.3 info: title: Student Information Management System version: 1.0.0 servers: - url: https://localhost:8081/api paths: /students: get: operationId: getStudents summary: Get all students responses: 200: description: Get all students successfully content: application/json: schema: type: array items: $ref: '#/components/schemas/Student' example: [{ "id": 1, "code": "001", "name": "Khanh" }, { "id": 2, "code": "002", "name": "Quan" }] /students/{id}: get: operationId: getStudentById summary: Get a student by id parameters: - name: id in: path description: "Id of the Student" required: true schema: type: string responses: 200: description: Get student information successfully content: application/json: schema: $ref: '#/components/schemas/Student' example: { "id": 1, "code": "001", "name": "Khanh" } delete: operationId: deleteStudentById summary: Delete a student by id parameters: - name: id in: path description: "Id of the Student" required: true schema: type: string responses: 200: description: Delete student information successfully content: application/json: schema: $ref: '#/components/schemas/Response' example: { "message": "Student deleted!"} components: schemas: Student: type: object properties: id: type: integer format: int64 code: type: string name: type: string Response: type: object properties: message: type: string |
Như các bạn thấy, chúng ta sử dụng từ khoá “$ref” với đường dẫn tới object mà chúng ta muốn sử dụng, thường bắt đầu với “components.schemas”, để khai báo data type kiểu object.
Việc định nghĩa API specs trước khi bắt tay vào implement API sẽ giúp chúng ta thống nhất được API contract, các bên liên quan chỉ cần follow theo API contract này để sử dụng, giảm thiểu rất nhiều rủi ro có thể xảy ra. Hãy suy nghĩ tới nó trước khi bắt đầu implement các API RESTful Web Service các bạn nhé!