Gerando Especificação OpenAPI com Go Lang e Swagger
OpenAPI é uma padrão de especificação de API, criado de maneira a facilitar o processo de desenvolvimento e o entendimento do que a API realiza, de uma maneira simples em que programadores e utilizadores da API possam ler, utilizar e experimentar o seu funcionamento de forma simples e rápida.
O HTTP Swagger é um wrapper para automatizar a geração de especificação de API utilizando Swagger versão 2.0.
Os PROs gerando a documentação da API dessa forma são:
approach documentação como código.
a documentação fica próxima da função que a utiliza, qualquer dúvida ou atualização, o que precisa ser consultado e atualizado estão próximos.
Em Go Lang, se algo está errado, o código não compila. Em outras palavras, se a definição da API estiver errada, eu logo noto e posso rapidamente corrigi-la.
Mão na massa!
1. O primeiro passo é iniciar o projeto:
1mkdir seu-projecto
2cd $_
3go mod init github.com/<seu-user>/seu-projeto
2. Inicie a API básica
Nesse exemplo crio duas funções, um endpoint GET e outro POST.
2.1 Endpoint básico para mostrar a versão da sua API
Utilizo o router Chi, porque preciso definir os verbos GET e POST no router, e não somente verificar o verbo na função. Por exemplo, tenho um endpoint fictício [GET] `/teste`, neste endpoint definimos a especificacão OpenAPI para este endpoint, quando quero um verbo [POST] para a mesma entidade, eu preciso de um router p/ definir qual função é responsável pelo [GET] e qual função é responsável pelo [POST], vou mostrar isso, na prática, um pouco mais a frente.
1func main() {
2 r := chi.NewRouter()
3 r.Get("/", version)
4 fmt.Println("API listening at port 3001...")
5 err := http.ListenAndServe(":3001", r)
6 if err != nil {
7 log.Fatal(err)
8 }
9}
P/ informar a minha API que uma especificação OpenAPI será criada, preciso criamos um endpoint chamado `/swagger`, e definimos a espcificacão inicial. Neste endpoint `/swagger` a documentação auto gerada estará disponível usando a UI do Swagger. P/ isso defino este endpoint na API da seguinte forma:
1r.Get("/swagger/*", httpSwagger.WrapHandler)
E adiciono a especificação OpenAPI p/ a função main, que ficará:
1// @title Titulo da sua API
2// @version 1.0
3// @description Descricão longa da sua API
4// @termsOfService http://swagger.io/terms/
5// @license.name Apache 2.0
6// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
7// @host localhost:3001
8// @BasePath /
9func main() {
10 r := chi.NewRouter()
11 r.Get("/", version)
12 r.Get("/swagger/*", httpSwagger.WrapHandler)
13 fmt.Println("API listening at port 3001...")
14 err := http.ListenAndServe(":3001", r)
15 if err != nil {
16 log.Fatal(err)
17 }
18}
Agora defino o exemplo p/ o endpoint `[GET] /` sem a especificação OpenAPI:
1
2func version(w http.ResponseWriter, r *http.Request) {
3 w.Write([]byte("version: 1.0.0"))
4}
E em seguida defino a especificacão OpenAPI da seguinte forma p/ este endpoint:
1// version godoc
2// @Summary Get API version
3// @Description Get API version
4// @Tags version
5// @Accept json
6// @Produce json
7// @Success 200 {object} string
8// @Router / [get]
2.2 Adicionando os imports necessários
O primeiro import é importante p/ informar onde a minha definição da API está localizada, em seguida importo o router e o http-swagger que é responsável em ler os comentários e transformar em especificação no formato OpenAPI.
Primeiro instalo a biblioteca Chi:
1go get -u github.com/go-chi/chi/v5
2go get -u github.com/swaggo/swag/cmd/swag
3go get -u github.com/swaggo/http-swagger
E adiciono os importes:
1_ "github.com/converge/strave-stories/docs" // docs is generated by Swag CLI, you have to import it.
2"github.com/go-chi/chi/v5"
3httpSwagger "github.com/swaggo/http-swagger"
4
3. Utilizando a ferramenta Swag p/ fazer o parser e gerar a especificação OpenAPI
Neste ponto já posso chamar o `Swag`, que criará os arquivos necessários, p/ posteriormente chamarmos o Swagger UI, que é a página web que mostra a documentação que especificamos nos comentários das funções, e também inicio a API para que a página fique exposta na API.
Então novamente, os passos p/ gerar a documentão e iniciar o Swagger UI são:
1swag init
2go run main.go
Agora é possível access o Swagger UI através do endereço http://localhost:3001/swagger/
Adicionando endpoint /my-bike para o verbo [GET]
É tão claro e fácil, que agora somente lendo o código é possível identificar como gerar documentação através dos comentários funciona, e como a OpenAPI é simples e gostosa de trabalhar.
1
2// listMyBike
3// @Summary List My Bike
4// @Description List details of My Bike
5// @Tags listMyBike
6// @Accept json
7// @Produce json
8// @Success 200 {object} Bike
9// @Router /my-bike [GET]
10func listMyBike(w http.ResponseWriter, r *http.Request) {
11err := json.NewEncoder(w).Encode(myBike)
12if err != nil {
13log.Println(err)
14}
15}
Adicionando endpoint /my-bike para o verbo [POST]
Seguindo a ideia anterior, esta é a definição p/ o método POST:
1// createMyBike
2// @Summary Create a Bike
3// @Description Create a Bike
4// @Tags createMyBike
5// @Accept json
6// @Produce json
7// @param body body Bike true "Bike Object"
8// @Success 201 {object} Bike
9// @Router /my-bike [POST]
10func createMyBike(w http.ResponseWriter, r *http.Request) {
11 reqBody, err := ioutil.ReadAll(r.Body)
12 if err != nil {
13 log.Println(err)
14 }
15 defer r.Body.Close()
16 json.Unmarshal(reqBody, &myBike)
17 if err != nil {
18 log.Println(err)
19 }
20 w.Write([]byte("Bike created!"))
21}
Um exemplo completo e funcionando está disponível https://github.com/converge/my-bike-api.