Pular para o conteúdo principal

Tools

Existem inúmeras ferramentas para auxiliar o OpenAPI.

Podemos procurar algumas em:

O Swaggerhub oferece toda uma suite para isso com geradores de código e tudo mais, depois faça um overview lá e veja se funciona pra você. Independente de tudo é sempre bom conhecer as coisas.

Vamos falar sobre o OpenAPI Generator que apesar desse nome inclui vários recursos além da geração de código. O repositório do OpenAPI Generator no Github pode ser útil também para ajudar.

A vantagem do uso de ferramentas como essa é a quantidade de patrocinadores que ela tem. Indo direto para a documentação oficial temos várias maneiras de usar.

Já com a ferramenta instalada no terminal temos o seguinte:

❯ openapi-generator --version  
openapi-generator-cli 7.10.0
commit : 12dfe8f
built : -999999999-01-01T00:00:00+18:00
source : https://github.com/openapitools/openapi-generator
docs : https://openapi-generator.tech/

❯ openapi-generator
usage: openapi-generator-cli <command> [<args>]

The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
list Lists the available generators
meta MetaGenerator. Generator for creating a new template set and configuration for Codegen. The output will be based on the language you specify, and includes default templates to include.
validate Validate specification
version Show version information used in tooling

See 'openapi-generator-cli help <command>' for more information on a specific
command.

Para quem não quiser instalar a ferramenta pode usar o docker. O comando openapi-generator é o entrypoint do container. Faça um alias no seu shell, é uma proposta interessante também.

docker run --rm \
-v ${PWD}:/local openapitools/openapi-generator-cli
usage: openapi-generator-cli <command> [<args>]

The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
list Lists the available generators
meta MetaGenerator. Generator for creating a new template set and configuration for Codegen. The output will be based on the language you specify, and includes default templates to include.
validate Validate specification
version Show version information used in tooling

See 'openapi-generator-cli help <command>' for more information on a specific
command.

Já usamos para validar a api que fizemos, mas vamos utilizar novamente para lembrar

# Tudo certo
❯ openapi-generator validate -i infoapi.yaml
Validating spec (infoapi.yaml)
No validation issues detected.

Forçando um erro para testar.

security:
# - BasicAuth: []
# - JwtAuthToken: []

Vou fazer usando o docker para entender o processo.

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli validate -i /local/infoapi.yaml
Validating spec (/local/infoapi.yaml)
Errors:
- attribute security is not of type `array`

[error] Spec has 1 errors.

Podemos gerar o código a partir desta api. A lista esta disponível aqui e podemos ver pela cli.

openapi-generator list  
The following generators are available:

CLIENT generators:
- ada
- android
- apex
- bash
- c
- clojure
- cpp-qt-client
- cpp-restsdk
- cpp-tiny (beta)
- cpp-tizen
- cpp-ue4 (beta)
- crystal (beta)
- csharp
- dart
- dart-dio
- eiffel
- elixir
- elm
- erlang-client
- erlang-proper
- gdscript
- go
- groovy
- haskell-http-client
- java
- java-helidon-client (beta)
- java-micronaut-client (beta)
- javascript
- javascript-closure-angular (beta)
- javascript-flowtyped
- jaxrs-cxf-client
- jetbrains-http-client (experimental)
- jmeter
- julia-client (beta)
- k6 (beta)
- kotlin
- lua (beta)
- n4js (beta)
- nim (beta)
- objc
- ocaml
- perl
- php
- php-dt (beta)
- php-nextgen (beta)
- powershell (beta)
- python
- python-pydantic-v1
- r
- ruby
- rust
- scala-akka
- scala-gatling
- scala-http4s
- scala-pekko
- scala-sttp
- scala-sttp4 (beta)
- scalaz
- swift-combine
- swift5
- swift6 (beta)
- typescript (experimental)
- typescript-angular
- typescript-aurelia
- typescript-axios
- typescript-fetch
- typescript-inversify
- typescript-jquery
- typescript-nestjs (experimental)
- typescript-node
- typescript-redux-query
- typescript-rxjs
- xojo-client
- zapier (beta)


SERVER generators:
- ada-server
- aspnet-fastendpoints
- aspnetcore
- cpp-pistache-server
- cpp-qt-qhttpengine-server
- cpp-restbed-server
- cpp-restbed-server-deprecated
- csharp-functions
- erlang-server
- fsharp-functions (beta)
- fsharp-giraffe-server (beta)
- go-echo-server (beta)
- go-gin-server
- go-server
- graphql-nodejs-express-server
- haskell
- haskell-yesod (beta)
- java-camel
- java-helidon-server (beta)
- java-inflector
- java-micronaut-server (beta)
- java-microprofile
- java-msf4j
- java-pkmst
- java-play-framework
- java-undertow-server
- java-vertx-web (beta)
- java-wiremock (beta)
- jaxrs-cxf
- jaxrs-cxf-cdi
- jaxrs-cxf-extended
- jaxrs-jersey
- jaxrs-resteasy
- jaxrs-resteasy-eap
- jaxrs-spec
- julia-server (beta)
- kotlin-server
- kotlin-spring
- kotlin-vertx (beta)
- kotlin-wiremock (beta)
- nodejs-express-server (beta)
- php-flight (experimental)
- php-laravel
- php-lumen
- php-mezzio-ph
- php-slim4
- php-symfony
- python-aiohttp
- python-blueplanet
- python-fastapi (beta)
- python-flask
- ruby-on-rails
- ruby-sinatra
- rust-axum (beta)
- rust-server
- scala-akka-http-server (beta)
- scala-cask
- scala-finch
- scala-http4s-server
- scala-lagom-server
- scala-play-server
- scalatra
- spring


DOCUMENTATION generators:
- asciidoc
- cwiki
- dynamic-html
- html
- html2
- markdown (beta)
- openapi
- openapi-yaml
- plantuml (beta)


SCHEMA generators:
- avro-schema (beta)
- graphql-schema
- ktorm-schema (beta)
- mysql-schema
- postman-collection (beta)
- protobuf-schema (beta)
- wsdl-schema (beta)


CONFIG generators:
- apache2

Agora vamos gerar um código a partir da especificação da API que temos. Cada linguagem que queremos gerar código nos oferecem diferentes tipos de personalizações. As configurações para geração de código em go também podem ser vistas pela CLI.

❯ openapi-generator config-help -g go  

CONFIG OPTIONS

disallowAdditionalPropertiesIfNotPresent
If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default. (Default: true)
false - The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
true - Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.

enumClassPrefix
Prefix enum with class name (Default: false)

generateInterfaces
Generate interfaces for api classes (Default: false)

generateMarshalJSON
Generate MarshalJSON method (Default: true)

generateUnmarshalJSON
Generate UnmarshalJSON method (Default: true)

hideGenerationTimestamp
Hides the generation timestamp when files are generated. (Default: true)

isGoSubmodule
whether the generated Go module is a submodule (Default: false)

packageName
Go package name (convention: lowercase). (Default: openapi)

packageVersion
Go package version. (Default: 1.0.0)

prependFormOrBodyParameters # Vamos usar isso aqui no exemplo jajá.
Add form or body parameters to the beginning of the parameter list. (Default: false)

structPrefix
whether to prefix struct with the class name. e.g. DeletePetOpts => PetApiDeletePetOpts (Default: false)

useDefaultValuesForRequiredVars
Use default values for required variables when available (Default: false)

useOneOfDiscriminatorLookup
Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. (Default: false)

withAWSV4Signature
whether to include AWS v4 signature support (Default: false)

withGoMod
Generate go.mod and go.sum (Default: true)

withXml
whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML) (Default: false)

Um comando que é bom conhecer e apesar de não estar na CLI é o completion que nos ajuda usar melhor a CLI.

# O que podemos fazer a partir do validate?
❯ openapi-generator completion validate
--recommend
-i
--input-spec

❯ openapi-generator validate -i infoapi.yaml --recommend
Validating spec (infoapi.yaml)
Warnings:
- While technically allowed, GET/HEAD with request body may indicate programming error, and
is considered an anti-pattern.

[info] Spec has 1 recommendation(s).

##### ---------

❯ openapi-generator completion list
-s
--short
-i
--include
-d
--docsite
--github-nested-index


❯ openapi-generator list -s
ada,ada-server,android,apache2,apex,asciidoc,aspnet-fastendpoints,aspnetcore,avro-schema,bash,crystal,c,clojure,cwiki,cpp-qt-client,cpp-qt-qhttpengine-server,cpp-pistache-server,cpp-restbed-server,cpp-restbed-server-deprecated,cpp-restsdk,cpp-tiny,cpp-tizen,cpp-ue4,csharp,csharp-functions,dart,dart-dio,eiffel,elixir,elm,erlang-client,erlang-proper,erlang-server,fsharp-functions,fsharp-giraffe-server,gdscript,go,go-echo-server,go-server,go-gin-server,graphql-schema,graphql-nodejs-express-server,groovy,kotlin,kotlin-server,kotlin-spring,kotlin-vertx,kotlin-wiremock,ktorm-schema,haskell-http-client,haskell,haskell-yesod,java,jaxrs-cxf-client,java-helidon-client,java-helidon-server,java-inflector,java-micronaut-client,java-micronaut-server,java-msf4j,java-pkmst,java-play-framework,java-undertow-server,java-vertx-web,java-camel,jaxrs-cxf,jaxrs-cxf-extended,jaxrs-cxf-cdi,jaxrs-jersey,jaxrs-resteasy,jaxrs-resteasy-eap,jaxrs-spec,javascript,javascript-flowtyped,javascript-closure-angular,java-wiremock,jetbrains-http-client,jmeter,julia-client,julia-server,k6,lua,markdown,java-microprofile,mysql-schema,n4js,nim,nodejs-express-server,objc,ocaml,openapi,openapi-yaml,plantuml,perl,php,php-flight,php-nextgen,php-laravel,php-lumen,php-slim4,php-symfony,php-mezzio-ph,php-dt,postman-collection,powershell,protobuf-schema,python,python-pydantic-v1,python-fastapi,python-flask,python-aiohttp,python-blueplanet,r,ruby,ruby-on-rails,ruby-sinatra,rust-axum,rust,rust-server,scalatra,scala-akka,scala-cask,scala-pekko,scala-akka-http-server,scala-finch,scala-gatling,scala-http4s,scala-http4s-server,scala-lagom-server,scala-play-server,scala-sttp,scala-sttp4,scalaz,spring,dynamic-html,html,html2,swift5,swift6,swift-combine,typescript,typescript-angular,typescript-aurelia,typescript-axios,typescript-fetch,typescript-inversify,typescript-jquery,typescript-nestjs,typescript-node,typescript-redux-query,typescript-rxjs,wsdl-schema,xojo-client,zapier

Você deve ter observado que temos geração tanto do lado do cliente quanto do lado do servidor. Obviamente que o código gerado para o lado do cliente é diferente do código gerado do lado do servidor.

Vamos conhecer um pouco melhor esse comando mas podemos consultar a documentação do generate também.

# Irá observar que ele mostra tanto os comando short quanto por extenso.
❯ openapi-generator completion generate
-e
--engine
-a
--auth
--global-property
--library
-v
--verbose
--schema-mappings
--enable-post-process-file
--skip-validate-spec
--inline-schema-options
--server-variables
--artifact-id
--api-name-suffix
--operation-id-name-mappings
-c
--config
--release-note
-g # Vamos usar
--generator-name
--generate-alias-as-model
-s
--skip-overwrite
--name-mappings
--enum-name-mappings
--log-to-stderr
--git-repo-id
--legacy-discriminator-behavior
--instantiation-types
--invoker-package
--model-package
--ignore-file-override
-o
--output
--model-name-suffix
--parameter-name-mappings
--api-package
--model-name-mappings
--git-host
--strict-spec
--type-mappings
--git-user-id
--merged-spec-filename
--openapi-generator-ignore-list
--openapi-normalizer
-p
--additional-properties
--minimal-update
--remove-operation-id-prefix
--dry-run
--language-specific-primitives
--skip-operation-example
--http-user-agent
-t
--template-dir
--model-name-prefix
--inline-schema-name-mappings
--reserved-words-mappings
--import-mappings
--artifact-version
--group-id
--input-spec-root-directory
--package-name
-i
--input-spec

Por exemplo, vimos que temos em go a opção de configuração prependFormOrBodyParameters que marquei la em cima. Para mudar essa opção podemos setar diretamente no comando.

#--dry-run é só uma simulação para não executar e ve o comando funciona e qual seria nossa saída
openapi-generator-cli generate -g go --additional-properties=prependFormOrBodyParameters=true -o ./out -i infoapi.yaml --dry-run
# Para passar várias opções --additional-properties=key1=value1,key2=value2

Mas você não pode ficar fazendo isso. Crie um arquivo generatorconfig-go.yaml com a configuração dos parâmetros e vamos apontá-lo.

prependFormOrBodyParameters: true
# key2: value2
# key3: value3
❯ openapi-generator generate -i infoapi.yaml -g go -c generatorconfig-go.yaml  -o ./goproject --dry-run

Você ainda pode mover todos os argumentos que fizemos acima para um arquivo yaml ou json usando o batch. Não vou documentar aqui mas é bom conhecer.

Dependendo do gerador escolhido iremos gerar o código do lado do cliente ou do lado do servidor.

Gerando um código em go do lado do servidor precisamos usar o generator go-server.

❯ openapi-generator generate -i infoapi.yaml -g go-server  -o ./go-server  
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/Users/davidprata/Desktop/gitlab/devsecops/docs/development/openapi//docs/development/openapi/resources/./go-server) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: go-server (server)
### ... REMOVIDO PARA FACILITAR A LEITURA

Agora gerando do lado do client vamo usar o generator go.

❯ openapi-generator generate -i infoapi.yaml -g go  -o ./go-client
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/Users/davidprata/Desktop/gitlab/devsecops/docs/development/openapi//docs/development/openapi/resources/./go-client) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: go (client)
[main] INFO o.o.codegen.DefaultGenerator - Generator 'go' is considered stable.
### ... REMOVIDO PARA FACILITAR A LEITURA
# Arquivos diferente para projetos diferentes
ls go-client
README.md docs model_beer_order.go model_paged_response_pageable.go
api git_push.sh model_beer_order_line.go model_paged_response_pageable_sort.go
api_beer.go go.mod model_beer_paged_list.go response.go
api_customer.go go.sum model_brewery.go test
api_order_service.go model__v1_customers__customer_id__orders_post_request.go model_customer.go utils.go
client.go model_address.go model_customer_paged_list.go
configuration.go model_beer.go model_paged_response.go

ls go-server
Dockerfile README.md api go go.mod main.go