Boas-vindas ao curso de documentação de API REST no padrão OpenAPI com o Swagger! Meu nome é Thiago Bussola e serei seu instrutor!
Audiodescrição: Thiago é um homem branco, de cabelos lisos e curtos na cor castanho-escuro com alguns fios grisalhos. Possui sobrancelhas grossas, barba, bigode e cavanhaque também na cor castanho-escuro. Usa um óculos de armação quadrada na cor preta e veste uma camiseta amarela. À sua frente, um microfone na altura do pescoço. Ao fundo, uma estante com livros e objetos decorativos.
Uma das atividades que realizamos diariamente como pessoas desenvolvedoras é acessar documentações de API externas para integração. Vamos abrir uma página, por exemplo, da Giphy Developers, que o Discord e várias outras plataformas utilizam para buscar GIFs. Para implementar isso, há uma série de regras e endpoints que podemos utilizar, os quais são bastante interessantes.
Toda essa informação está documentada para facilitar o acesso de pessoas desenvolvedoras, clientes e pessoas responsáveis pelo produto, permitindo que compreendam como essa documentação funciona. Temos o exemplo da Poké API, que é bem conhecida e já fornece algumas informações, incluindo uma parte interativa e uma descrição do que cada rota faz.
A ideia é que possamos pegar uma documentação pronta, entender seu funcionamento interativo e, em seguida, adicionar algumas rotas. Como o padrão da OpenAPI tende a ser sempre o mesmo, trabalharemos com uma estrutura de documentação já pronta, que pode ser editada para nossas APIs.
Temos um projeto de API REST simples com duas entidades: user
e books
. Estamos realizando uma autenticação básica com JWT e temos um arquivo swagger.json
que contém a documentação seguindo o padrão OpenAPI. Precisamos estar atentos a alguns detalhes do projeto, como a configuração do tsconfig.json
. Habilitamos a flag resolveJsonModule: true
para permitir a importação de arquivos JSON. Assim, se quisermos importar um arquivo .json
, essa flag deve estar habilitada.
Temos uma página no localhost chamada api-docs
, que ainda não está funcionando. Precisamos habilitar o Swagger na aplicação. A partir do terminal, vamos instalar o Swagger com o comando npm install swagger-ui-express
.
npm install swagger-ui-express
Em seguida, instalamos @types/swagger-ui-express
como dependência de desenvolvimento com npm install @types/swagger-ui-express --save-dev
.
npm install @types/swagger-ui-express --save-dev
No arquivo de configuração da API, temos uma classe chamada app
, onde configuramos os middlewares, a base de dados e os arquivos de rota. No middleware
, configuramos o Express. Vamos adicionar this.express.use();
.
private middleware(): void {
this.express.use(express.json());
this.express.use()
}
Antes de prosseguir, importamos a biblioteca swaggerUi
e o arquivo JSON com import swaggerUi from 'swagger-ui-express';
e import swaggerJson from './swagger.json';
.
import swaggerUi from 'swagger-ui-express';
import swaggerJson from './swagger.json';
Feito isso, podemos passar os seguintes parâmetros para this.express.use()
: "/api-docs"
, swaggerUi.serve
e swaggerUi.setup(swaggerJson)
.
private middleware(): void {
this.express.use(express.json());
this.express.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerJson));
}
Estamos utilizando o banco de dados MongoDB. Então, para executar o projeto, estando na pasta principal, será necessário executar docker compose up -d
no terminal para subir o banco de dados.
Voltamos à página de documentação, atualizamos e, após levantar o servidor com npm start
, a documentação estará disponível. A documentação do Swagger é interativa, permitindo operações como deletar, atualizar e buscar livros.
swagger.json
No arquivo swagger.json
, especificamos que estamos usando o padrão 3.0 da OpenAPI. Se houver algo no trabalho que utilize uma versão diferente, o arquivo mudará. Para documentações novas, recomenda-se usar a versão mais recente, 3.0. Podemos dar um título à documentação, que será atualizado automaticamente. Assim, deixamos o arquivo pronto, realizando poucas alterações.
Para definir as rotas, abrimos uma tag chamada paths
. Em seguida, especificamos o caminho /books
e indicamos que pode haver um método post
. O post
terá a tag Books
para separar a documentação.
No post
, definimos um requestBody
, cujo content
será application/json
, e incluímos um schema
, definido mais abaixo, no components
. No caso, temos um schema
de Book
para usar em todas as rotas que precisem de um exemplo. Aqui, definimos o exemplo, com um livro semi pronto para o usuário ver como cadastrar um livro, um autor e um ISBN.
As respostas já estão definidas de acordo com a API. No arquivo book.controller.ts
, retornamos códigos como 200, 500, 201 e 400. Portanto, a documentação deve estar de acordo com o que foi escrito na API.
Temos também as rotas. No caso da busca por título, passamos o parâmetro title
e temos books/{id}
. Quando passamos por id
, podemos fazer um put
. Teremos parameters
e também um requestBody
. Se chamarmos a mesma rota books/{id}
com o verbo delete
, haverá um comportamento diferente na documentação.
Vamos ver essa documentação interagindo rapidamente. Acessamos a documentação e começamos a interagir com ela. Primeiro, abrimos a tag Books
, onde podemos armazenar todas as rotas semelhantes. Se tivermos outros segmentos de rota, conseguimos separá-los de forma mais organizada.
Em seguida, abrimos Create a book
e clicamos em Try it out
para fazer uma requisição. Podemos cadastrar o livro do exemplo.
{
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"ISBN": "9780744066868"
}
Ao executar, o sistema informa que o livro foi cadastrado, retornando o id
, já que estamos usando o MongoDB, e o status 201. No banco, usando o MongoDB Compass, verificamos na tabela books
que o livro foi cadastrado.
Podemos cadastrar mais um e alterar o ISBN para 9780744066999
:
{
"title": "O Senhor dos Aneus",
"author": "JRR Tolkien",
"ISBN": "9780744066999"
}
Ao executar, o registro é cadastrado no banco.
Na parte de listagem, temos um Get all books
. Podemos fazer um Try it out
, executar e ver os dois livros cadastrados.
Na busca por títulos Find a book by title
, podemos buscar por título. Clicamos em Try it out
para liberar o parâmetro, buscamos por "O Senhor dos Aneis" e ele retorna corretamente o livro pesquisado.
Na tag de atualização do livro, Update a book
, pegaremos o ID do primeiro livro, que já está na documentação, e faremos um Try it out
para atualizá-lo. Vamos alterar o título para "Código Limpo", o autor para Robert Martin e o ISBN para qualquer valor.
{
"title": "O Código Limpo",
"author": "Robert Martin",
"ISBN": "123654987"
}
Ao executar, a atualização é confirmada. Verificamos pela documentação e o livro "O Código Limpo" de Robert Martin está presente.
Vamos copiar o ID do livro atualizado e utilizar a tag de exclusão, Delete a book
, para excluir o livro pela documentação. Após executar, confirmamos que apenas um registro permanece no banco. De volta à documentação, ao listar todos os livros, verificamos que há apenas um item no array.
Essa é a forma de usar a documentação. Para novos integrantes da equipe ou pessoas de produto, a documentação permite interação e compreensão das regras de negócio da aplicação. Podemos adicionar descrições sobre parâmetros, funcionamento e respostas, tornando a documentação amigável para quem a utiliza. É comum termos várias APIs de pagamento no Brasil que precisam ser integradas ao sistema, e a documentação é essencial para isso.
No próximo vídeo, vamos adicionar a entidade de usuários, incluindo cadastro e autenticação. Mostraremos como restringir o uso de uma rota apenas para usuários autenticados. Também apresentaremos outra forma de documentar, além do JSON, utilizando YAML. Podemos criar arquivos grandes de documentação, mas também é possível documentar diretamente na rota com comentários, o que é uma abordagem interessante. Nos vemos no próximo vídeo!
Vamos adicionar uma nova rota à nossa documentação!
Ao acessar os arquivos do sistema, podemos ver que temos um user.schema
bem simples, onde o usuário é composto apenas por nome e senha. Realizamos a autenticação criptografando a senha. Atualmente, temos duas rotas no auth.routes
: uma para registro e outra para login do usuário.
/auth/register
)De volta ao swagger.json
, fara facilitar o trabalho, vamos minimizar tudo que é relacionado a books
, como books/{title}
e book/{id}
. Dentro de paths
, adicionaremos uma vírgula e inseriremos a nova rota, que será /auth/register
.
Para registrar, utilizaremos o método post
. No summary
, podemos descrever o que essa rota faz, como "Create a user"
. Em seguida, adicionaremos uma nova tag tags
e passamos um array com Auth
.
"paths": {
"/books": { ... },
"/books/{title}": { ... },
"/books/{id}": { ... },
"/auth/register": {
"post": {
"summary": "Create a User",
"tags": [
"Auth"
]
}
Após salvar, ao atualizar a tela da documentação, podemos ver que agora temos duas seções: uma para registro, que ainda está em desenvolvimento, e outra para livros. Vamos continuar configurando essa rota. É importante escrever parte por parte e conferir se tudo está correto.
requestBody
)Na propriedade requestBody
, definimos required
como true
, indicando que não pode ser deixado em branco. O content
será application/json
e passaremos um schema
do tipo object
. Não criamos um esquema específico para isso, pois será usado apenas para autenticação, demonstrando que nem tudo precisa de um esquema.
Definimos as properties
com username
do tipo string
e password
também do tipo string
.
"paths": {
"/books": { ... },
"/books/{title}": { ... },
"/books/{id}": { ... },
"/auth/register": {
"post": {
"summary": "Create a User",
"tags": [
"Auth"
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
}
}
}
}
responses
)Após o requestBody
, adicionamos uma vírgula e cadastramos as respostas. Para o caso de 201, que indica criação, a descrição será "Usuário cadastrado com sucesso"
. Passamos novamente o content
como application/json
e definimos um schema
com type object
. Nas properties
, incluímos uma message
do tipo string
.
"paths": {
"/books": { ... },
"/books/{title}": { ... },
"/books/{id}": { ... },
"/auth/register": {
"post": {
"summary": "Create a User",
"tags": [
"Auth"
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
},
"responses": {
"201": {
"description": "Usuário cadastrado com sucesso",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
Após salvar, ao atualizar a documentação, podemos expandir e ver username
, password
e a mensagem de resposta do tipo string
. Vamos testar o cadastro com username
como "Thiago Bussola" e senha "teste123" para facilitar:
{
"username": "Thiago Bussola",
"password": "string"
}
Ao executar, recebemos a mensagem "Usuário cadastrado com sucesso", conforme esperávamos. Vamos abrir nosso banco de dados, acessar a tabela de users
e realizar uma busca. O usuário está presente e a senha está criptografada.
/auth/login
)Vamos retornar ao nosso Visual Studio Code e continuar com a parte do login. Minimizamos o auth/register
para não nos perder e criamos uma nova rota: /auth/login
.
O login também será um post
, com o summary
Login User
, e as tags Auth
. O corpo da requisição será obrigatório, pois não podemos passar em branco, e o conteúdo será application/json
. O esquema será do tipo object
, com as propriedades username
e password
do tipo string
.
"/auth/login": {
"post": {
"summary": "Login User",
"tags": ["Auth"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
}
}
}
Após o requesteBody
, incluímos uma vírgula e implementamos o responses
da seguinte forma:
"/auth/login": {
"post": {
"summary": "Login User",
"tags": ["Auth"],
"requestBody": {...},
"responses": {
"200": {
"description": "Logado com sucesso",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"token": {
"type": "string"
}
}
}
}
}
}
}
}
}
Como atividade, você deve implementar os retornos de 401
logo abaixo do retorno 200
.
Vamos testar o login para ver se o token está retornando corretamente. Na documentação, abrimos a tag Login User
e clicamos em Try it out
. Utilizaremos o seguinte JSON de exemplo:
{
"username": "ThiagoBussola",
"password": "Teste123"
}
Ao executar, ele retorna um token. Não vamos copiá-lo ainda, mas temos a parte de autorização, permitindo o uso de determinadas rotas. Vamos entender o funcionamento.
Podemos restringir a rota Get all books
. No código do arquivo routes.ts
, adicionamos o verifyToken
, o middleware de autenticação que pode ser aplicado em quantas rotas quisermos.
routes.post("/books", bookController.create);
routes.get("/books", verifyToken, bookController.find);
routes.get("/books/:title", bookController.findByTitle);
routes.put("/books/:id", bookController.update);
routes.delete("/books/:id", bookController.delete);
Ao tentar usar a rota sem estar logado, recebemos a mensagem de que o token não foi provisionado. No entanto, o cadastro de um livro é permitido para qualquer pessoa. Apenas a busca é restrita a usuários autenticados.
Vamos autenticar novamente, copiar o token e utilizá-lo para autorizar. Após isso, a rota de busca funciona e retorna os livros.
swagger-jsdoc
A próxima etapa é documentar de outra forma, usando comentários. Vamos apagar a parte escrita manualmente de auth/login
e auth/register
, salvar, e atualizar a documentação. As seções deletadas do código também desaparecem da documentação.
Em seguida, precisamos instalar a biblioteca swagger-jsdoc
com npm install swagger-jsdoc
.
npm install swagger-jsdoc
Para evitar conflitos, desabilitaremos a documentação atual. No arquivo app.ts
, comentamos um treco do código de private middleware()
, além da importação do swaggerJson
. Em seguida, movemos o arquivo swagger.json
para fora da pasta user
, renomeando-o para swagger-old.json
. A documentação ficará apenas com as rotas de autenticação.
Trechos de código com comentário:
// import swaggerJson from "./swagger.json";
private middleware(): void {
this.express.use(express.json());
// this.express.use(
// "/api-docs",
// swaggerUi.serve,
// swaggerUi.setup(swaggerJson)
// );
}
swagger-jsdoc
Criamos um arquivo que será disponibilizado, usando swagger-jsdoc
. Ele cria no formato de comentário, incluindo propriedades e exemplos do livro. A configuração é feita nas rotas auth/routes
e routes
, e o arquivo principal será swagger.ts
.
Código omitido.
Feito isso, precisamos instalar os tipos com npm install @types/swagger-jsdoc --save-dev
.
npm install @types/swagger-jsdoc --save-dev
No arquivo de API, app.ts
, mudamos para atender ao novo Swagger. Importamos como swaggerSpec
e configuramos o express para usar o novo endereço /docs
. A configuração é semelhante, mas agora o setup é o swaggerSpec
.
import swaggerSpec from "./swagger";
private middleware(): void {
this.express.use(express.json());
this.express.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));
// this.express.use(
// "/api-docs",
// swaggerUi.serve,
// swaggerUi.setup(swaggerJson)
// );
}
Ao acessar /docs
, vemos que não há rotas ainda. Vamos documentar rapidamente a rota de users
em auth.routes.ts
. Criamos uma rota para o registro, usando comentários multilinha. Usamos @swagger
e colamos o restante para facilitar. As propriedades são as mesmas do JSON, mas agora sem abrir o objeto a cada vez.
Código omitido.
Vamos testar o registro com os seguintes dados:
{
"username": "Matheus Augusto",
"password": "Teste123"
}
Ao executar, vemos que o registro é criado com sucesso.
Para o login, seguimos o mesmo processo, documentando com comentários. No routes.ts
, você deve passar a documentação para o formato de comentário em cima de cada rota.
Existem dois estilos de documentação: com comentários ou com arquivo JSON. A escolha depende de cada pessoa desenvolvedora, do time e da empresa. O importante é não faltar documentação. Escolha uma abordagem e documente suas rotas corretamente!
Nos vemos no próximo curso!
O curso Swagger: documentando APIs REST com OpenAPI possui 35 minutos de vídeos, em um total de 9 atividades. Gostou? Conheça nossos outros cursos de Node.JS em Programação, ou leia nossos artigos de Programação.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.