Tìm hiểu về Swagger – Công cụ viết document cho RESTfull APIs

APIs(Application Programming Interfaces) đang ngày càng trở nên phổ biến, các dịch vụ trên Internet hầu hết đều sử dụng chuẩn RESTfull APIs để cung cấp cho các đối tác 1 phần tài nguyên của mình sử dụng. Vậy ta đặt ra câu hỏi là làm sao để cho các đối tác biết mình được cung cấp những tài nguyên gì? Phải sử dụng những thông tin nào để có thể lấy được tài nguyên đó?

Chính vì thế, ta cần phải có 1 công cụ hỗ trợ việc tạo document APIs giúp thuận tiện cho việc cung cấp về cách sử dụng tài nguyên thông qua APIs 1 cách hiệu quả. Hôm nay chúng ta sẽ tìm hiểu về 1 công cụ khá nổi tiếng dùng để viết document APIs: Swagger.

Swagger là gì ?

Swagger là 1 open source dùng để phát triển, thiết kế, xây dựng và làm tài liệu cho các hệ thống RESTfull Web Service. Ta có demo của Swagger như sau:

Demo Swagger UI

Swagger cung cấp những công cụ hỗ trợ việc tạo doc: Swagger UI, Swagger Editor, Swagger Codegen, Swagger Hub, Swagger Inspector. Trong đó 3 công cụ đầu tiên là open source, Swagger Hub và swagger Inspector là những công cụ cao cấp hơn nhưng sẽ phải trả phí, tuy nhiên chúng ta có thể dùng free trong vòng 30 ngày. Vậy để cho thuận tiện, chúng ta sẽ tìm hiểu các viết doc APIs bằng SwaggerUI và sơ lược về Swagger Hub.

Swagger UI là 1 công cụ giúp gen 1 trang html css mô tả về các APIs được cấu hình bởi 1 file .yaml. Ngoài ra, công cụ này còn cho phép ta mockup đến api đó để xem kết quả (tất nhiên là api của bạn phải hoạt động được đã :D).

Cài đặt Swagger UI

Bước 1: Tải thư viện Swagger UI

Các bạn clone project Github này về, sau đó hãy copy thư mục dist trong project đó vào project của bạn và chọn render file index.html trong thư mục dist. Như trong project của tôi sử dụng Nodejs làm backend sẽ cấu hình như sau:

Khi đó, nếu ta chạy localhost:3000 trên trình duyệt, ta sẽ được trang demo Swagger UI bên trên.

Bước 2: Tạo config cấu hình các APIs của bạn

Cấu trúc cơ bản của 1 file .yaml trong Swagger như sau:

openapi: Phiên bản Swagger đang sử dụng, sẽ định nghĩa toàn bộ cấu trúc file .yaml

info: Thông tin của APIs, trong này sẽ chứa những phần: title, version, description, …

title: tên Open-APIs (thường là tên sản phẩm project mình làm)

vertion: Phiên bản APIs public

description: Mô tả về APIs

security: Authentication mà APIs sử dụng để cung cấp tài nguyên

paths: Các APIs mà bạn cung cấp cho đối tác

component: Định nghĩa các model sử dụng bởi APIs

Ngoài ra còn rất nhiều keyword khác có thể tham khảo ở trang document của Swagger.

Swagger cũng hỗ trợ viết config theo định dạng json, tuy nhiên chúng ta nên viết theo định dạng yaml.

Ta sẽ tạo file .yaml với cấu trúc như sau(được lấy ngay trong file demo của swagger) để cấu hình các APIs:


# Added by API Auto Mocking Plugin
servers:
- description: SwaggerHub API Auto Mocking
url:
info:
description: Test APIs document Swagger
version: "1.0.0"
title: APIs document Swagger
termsOfService: '
contact:
email:
license:
name: Apache 2.0
url: '
tags:
- name: user
description: Operations about user
paths:
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
responses:
default:
description: successful operation
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
description: Created user object
required: true
/user/login:
get:
tags:
- user
summary: Logs user into the system
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: true
schema:
type: string
- name: password
in: query
description: The password for login in clear text
required: true
schema:
type: string
responses:
'200':
description: successful operation
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
description: date in UTC when token expires
schema:
type: string
format: date-time
content:
application/json:
schema:
type: string
application/xml:
schema:
type: string
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
operationId: logoutUser
responses:
default:
description: successful operation
components:
schemas:
User:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
phone:
type: string
userStatus:
type: integer
format: int32
description: User Status
xml:
name: User
requestBodies:
UserArray:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
description: List of user object
required: true
securitySchemes:
test_auth:
type: oauth2
flows:
implicit:
authorizationUrl: '
scopes:
'write:users': modify your account
'read:users': read your information
api_key:
type: apiKey
name: api_key
in: header

openapi: 3.0.0# Added by API Auto Mocking Pluginservers:- description: SwaggerHub API Auto Mockingurl: https://virtserver.swaggerhub.com/test-swagger/1.0.0 info:description: Test APIs document Swaggerversion: "1.0.0"title: APIs document SwaggertermsOfService: ' http://swagger.io/terms/' contact:email: [email protected] license:name: Apache 2.0url: ' http://www.apache.org/licenses/LICENSE-2.0.html' tags:- name: userdescription: Operations about userpaths:/user:post:tags:- usersummary: Create userdescription: This can only be done by the logged in user.operationId: createUserresponses:default:description: successful operationrequestBody:content:application/json:schema:$ref: '#/components/schemas/User'description: Created user objectrequired: true/user/login:get:tags:- usersummary: Logs user into the systemoperationId: loginUserparameters:- name: usernamein: querydescription: The user name for loginrequired: trueschema:type: string- name: passwordin: querydescription: The password for login in clear textrequired: trueschema:type: stringresponses:'200':description: successful operationheaders:X-Rate-Limit:description: calls per hour allowed by the userschema:type: integerformat: int32X-Expires-After:description: date in UTC when token expiresschema:type: stringformat: date-timecontent:application/json:schema:type: stringapplication/xml:schema:type: string'400':description: Invalid username/password supplied/user/logout:get:tags:- usersummary: Logs out current logged in user sessionoperationId: logoutUserresponses:default:description: successful operationcomponents:schemas:User:type: objectproperties:id:type: integerformat: int64username:type: stringfirstName:type: stringlastName:type: stringemail:type: stringpassword:type: stringphone:type: stringuserStatus:type: integerformat: int32description: User Statusxml:name: UserrequestBodies:UserArray:content:application/json:schema:type: arrayitems:$ref: '#/components/schemas/User'description: List of user objectrequired: truesecuritySchemes:test_auth:type: oauth2flows:implicit:authorizationUrl: ' http://test-swagger.herokuapp.com' scopes:'write:users': modify your account'read:users': read your informationapi_key:type: apiKeyname: api_keyin: header

Như vậy, chỉ với khoảng 30 phút dọc document, ta có 1 file config khá đầy đủ về thông tin các APIs. Theo như cấu hình trên, ta có thể cấu hình các tài nguyên dữ liệu gửi lên APIs và dữ liệu APIs trả về dưới dạng model (cấu hình trong components/schemas) để có thể tái sử dụng lại.

Sau đó, chúng ta save file cấu hìn dưới dạng đuôi .yaml vào thư mục dist tại bước 1, ở đây tôi sẽ lưu thành swagger.yaml.

Bước 3: Cập nhật lại đường dẫn file config APIs và hưởng thụ thành quả

Bây giờ hãy mở file index.html trong thư mục dist, tìm và sửa path url của function SwaggerUIBundle thành đường dẫn chúng ta vừa tạo. Sau đó lưu lại, khởi chạy server, truy cập vào router đã trỏ tới tại bước 1 để hưởng thụ thành quả nào :D.

Sửa lại đường dẫn cấu hình APIs

Để cho dễ hình dung, các bạn hãy truy cập vào đây để xem document RESTfull APIs mà tôi vừa tạo ra 😀

Viết file .yaml cấu hình cho hiệu quả…

Một cái khá hay của file .yaml là chúng ta có thể tách riêng từng phần và gọi lại chúng nhờ dùng $ref. Chính vì điều này, chúng ta có thể tách các cấu trúc dữ liệu thành từng phần riêng biệt rồi gọi chúng lại. Điều này giúp file .yaml của chúng ta có 1 cấu trúc dễ nhìn dễ đọc và dễ hiểu.

2 cách viết cấu hình

Ngoài ra, file .yaml còn cho phép chúng ta tách riêng thành nhiều file .yaml tương ứng, chúng ta hoàn toàn có thể tách từng nhóm APIs cùng 1 nhiệm vụ thành các file riêng biệt, giúp tiết kiệm công sức đọc và sửa cấu hình sau này hơn.

Về Swagger Hub, dịch vụ 3 trong 1

Swagger Hub là 1 dịch vụ cung cấp tính phí của Swagger thích hợp cho các công ty sử dụng và public APIs cho các đối tác bằng việc generator APIs code, tuy nhiên chúng ta vẫn được sử dụng free trial trong 30 ngày. Swagger Hub có đầy đủ cả 3 công cụ open source, cung cấp 1domain cho phép chúng ta public Swagger UI, cung cấp tool gen code từ file cấu hình APIs và cung cấp cho chúng ta 1 công cụ để editor file .yaml cấu hình cho các APIs.

Để sử dụng dịch vụ này, tất nhiên là bạn phải đăng ký 1 tài khoản free trial tại trang này. Phần này dễ, các bạn tự làm được ✌️

Đăng ký 1 tài khoản Swagger Hub

Tiếp đến các bạn tạo mới APIs trên Swagger Hub, nó sẽ dẫn ta đến 1 trang Editor với định dạng file .yaml. Tương tự như cách viết .yaml chúng ta đã sử dụng ở Swagger UI.

Để xem Swagger UI chúng ta chọn Design View => Preview Docs.

Để Export ra code call APIs, chúng ta chọn Export, chọn dạng mà chúng ta muốn xuất ra.

Tuy nhiên sử dụng Swagger Hub lại có 1 nhược điểm là không tách thành cấu trúc file – thư mục, điều này gây file config rất dài và khó maintain. Bạn hãy thử tưởng tượng có 1 hệ thống 100 cái APIs cần public, kiểu dữ liệu to bự chảng … và sau đó câu hình lỗi 1 APIs thì sẽ sửa thế nào nhỉ 😝.

Trên đây, chúng ta đã tìm hiểu về 1 công cụ viết và quản lí document APIs khá dễ làm quen và tự viết được (dễ hơn cả code html 😛). Hi vọng bài viết này sẽ giúp ích cho project của các bạn. Cảm ơn vì đã đọc đến cuối bài viết !