Swagger
Swagger
Swagger
[00:00] Bem-vindos de volta. Conforme comentei, antes de definirmos end points, chamado aqui de
paths, vamos definir algumas informações a mais sobre nossa própria API, então podemos adicionar
algumas coisas que vão ser apresentados com links. Por exemplo, eu posso colocar uma
documentação externa, eu posso colocar os termos de serviço.
[00:23] Vamos adicionar exatamente isso. Eu não tenho termos de serviço reais para essa API, até
porque ela nem existe. Mas vamos colocar um link mentira, um link falso. Então posso adicionar a
chave terms “Ctrl + Espaço" que o Swagger Editor completa a chave automaticamente.
[00:40] Nessa chave "termsOfService" eu vou adicionar um link, que vai redirecionar a pessoa a
uma página quando ela clicar em TermsofService. Então vou colocar https://mockapi.io, quando ele
salvar já aparece o TermsofService no lado direito da página.
[00:55] Seu eu abrir o link TermsofService no lado direito em uma nova guia, ele vai abrir a página
"mockapi.io". Então como eu estou logado, ele já abre na área de projetos, vou fechar essa guia e
voltar par ao Editor.
[01:09] Eu posso adicionar documentação externa, imagina que eu tenho essa documentação viva,
onde a pessoa tem acesso a todos os end points, ela pode testar em tempo real e que eu tenho outra
documentação, um pouco mais formal. Com um texto super extenso, explicando o propósito de
cada coisa, um motivo para algo existir, ou ainda como você pode conseguir a chave de acesso, etc.
[01:34] Então se eu tenho uma documentação externa, além Swagger eu posso adicionar. Só não na
parte de info, vou adicionar outra chave, outro valor na raiz desse documento. O que eu quero dizer
com raiz, na raiz, até o momento, eu tenho o openapi, info e agora vou ter externalDocs. Ou seja,
uma documentação externa.
[01:55] Essa documentação externa, quando eu adiciono apenas a chave, aparece um erro no lado
direito da tela, que nos diz que ela precisa ser um objeto, então ela tem outras propriedades. Que
propriedades são essas? Quando dou um "Ctrl + Espaço" ele vai mostrar as opções description ou
URL.
[02:08] Ou seja, a descrição dessa documentação externa, que o que vai ficar escrito, e a URL que
exatamente o link. Eu posso escrever nessa chave "Documentação burocrática", então algo que faça
sentido para a sua API. Já na URL, que é obrigatório eu posso colocar também aquele mesmo link,
https://mockapi.io, e vai aparecer para nós no lado direito da tela "Documentação burocrática".
[02:30] De novo, seu eu abro o link "Documentação burocrática" em uma nova guia, ele vai abrir o
link do MockAPI. Dessa forma conseguimos adicionar links, eu consigo adicionar termos de
serviço, eu consigo adicionar documentação externa, eu poderia colocar qualquer coisa aqui,
mesmo que não fosse uma documentação externa.
[02:46] Como, por exemplo, o site para os nossos planos, "saiba mais sobre nossos planos" como
um link acessível. Você pode colocar qualquer coisa, então temos acesso a uma descrição e a uma
URL. Vou deixar escrito “Documentação burocrática” mesmo, porque podemos fingir que é só uma
documentação externa.
[03:03] Já vamos avançando na definição da nossa API, assim existe uma infinidade do que
podemos fazer aqui, então não quero me estender muito. Mas no próximo vídeo eu vou adicionar só
um pouco mais detalhes. Por exemplo, informações de contato, para quem a pessoa vai enviar um e-
mail se tiver algum problema?
[03:20] E a licença, esta API pode ser utilizado por qualquer pessoa? É uma API pública ou é uma
exclusiva? Qual a licença dessa API, como a pessoa vai saber como ela pode utilizar. Então que
adicionar essas duas informações no próximo vídeo.
Complementando infos
[00:00] Bem vindos de volta. Como eu disse, quero adicionar algumas informações a mais para essa
API. Primeiro, a licença, ou seja, como a pessoa pode utilizar a API, e algum dado de contato.
Vamos começar pelo contato, se eu começar a escrever contato e apertar em "Ctrl + Espaço" para
completar, eu posso adicionar um contato diretamente, e eu vejo que contato também é um objeto.
[00:20] O contrato ele pode ter um nome, um e-mail e uma URL. Vamos começar com o nome, vou
colocar nome: Suporte a Devs. E esse suporte a devs vai ter comente um e-mail, que vai ser
email: [email protected]. Então vai aparecer no lado direito da tela a opção "Contact
Suporte a Devs" e se eu clicar, ele vai abrir algo de e-mail para enviar um e-mail para lá.
[00:49] Se eu quiser ter uma URL, eu posso ter uma, url: https://mockapi.io. No lado
direito já aparece o website, ou seja, o link para este Suporte a Devs ou enviar um e-mail para o
Suporte a Devs. Então conseguimos ter essas duas informações quando estamos falando sobre
contatos. Ou um Website, ou um e-mail ou ambos.
[01:15] Então já temos as informações de contato, eu quero adicionar uma licença, eu quero
informar que essa API tem como licença a GPL 3 que é General Public License, alguma coisa
assim. Eu posso adicionar uma license:, e a licença também é um objeto, ela tem o nome da
licença e a URL da licença. Vamos começar com o nome, que vai ser nome: GPLv3 e a URL
desta licença é esse link, url: https://www.gnu.org/licenses/gpl-3.0.html.
[01:46] Se eu clicar nesse link ele abre o site da GNU, em específico da "General Public License".
No lado direito é possível perceber que licença é essa. Já aparece o link para a pessoa acessar, ler e
saber tudo que ele precisa em relação à licença da nossa API. Eu posso escrever o que eu quiser no
license, não é obrigatório estar escrito o nome da licença específico, mas obviamente faz sentido
que o utilize.
[02:19] Posso ainda colocar como name: "Licença: GPLv3", entre aspas para aparecer os
dois pontos, informando que a licença é a GPLv3. Dessa forma conseguimos ter vários links de
apoio na nossa API, além da descrição, título, versão e claro, temos informações extras.
[02:37] Já coloquei um monte de links nessa documentação, mas tem um erro continua aparecendo.
Eu quero definir o que essa API faz realmente, eu quero definir os paths, ou os end pints, as URLs
disponíveis nesta API. É exatamente nisso que iremos focar no próximo capítulo.
Para saber mais: Info Object
Neste capítulo nós utilizamos as chaves externalDocs e info. Todas as chaves que usamos
possuem alguns campos obrigatórios e outros opcionais.
Nesse link você pode conferir os campos de info: https://swagger.io/specification/#info-object
Recursos e verbos
[00:00] Boas-vindas a mais um capítulo desse treinamento, onde estamos brincando um pouco com
a documentação de uma API usando o Swagger. Agora eu quero tornar o que já fizemos um pouco
mais funcional, tentar, pelo menos, fazer uma requisição, para buscar todas as especialidades. Para
isso eu preciso definir os paths.
[00:20] Então vamos definir o paths, adicionando a chave "paths:" e se eu dou um "Enter" aparece o
erro no lado direito da tela me avisando que isso é um objeto. Precisamos definir chaves e valores,
as chaves desse objeto vão ser as URLs, por exemplo, a chave /especialidades:. E o valor de
cada uma dessas chaves é outro objeto também.
[00:42] Podemos ter, nesse caso, os verbos, por exemplo, eu quero o verbo get: e esse verbo pode
ter algumas informações como o sumary:, a descrição, o que isso realmente é. Então eu posso
colocar sumary: Recupera todas as especialidades. Já começamos e na parte
direita da tela já apareceu um detalhe, que é de um end point, de um path na nossa API.
[01:12] Inclusive se clicar nesse path ele me mostra parâmetros, que eu não tenho ainda, e ele me
mostraria as possíveis respostas, que também não tenho. Mas eu quero atentar para outro detalhe, o
"Default". Nós temos essa informação, essa API e quando eu tento fazer um execute, não acontece
nada, ele não nos devolve nada.
[01:38] Porque ele está tentando acessar editor.swagger.io/especialidades. Eu não tenho nenhum
servidor informado, antes do default não tem nada informando qual é o servidor que eu estou
acessando. Então antes de termos paths, eu preciso ter servidores. Teremos que adicionar um
servidor, reparem que servers é um array, podemos inclusive ter mais de um servidor.
[02:05] Então eu vou adicionar um array, onde eu posso informar a URL, - url:,
description:. Clicar em “API de Teste” e eu vou pegar a URL da nossa API, que é "-url:
http//mockapi.io/projects/6096015d116f300174b29bb". Ou seja, quando eu fizer um teste agora o
que o Swagger vai tentar acessar é essa URL que acabei de adicionar, incluindo o "/especialidades”,
usando o verbo get, sem passar parâmetro nenhum.
[02:35] Então eu poderia ter mais de uma URL, imagina que eu quero ter uma documentação que
possa acessar o nosso servidor de teste e o servidor de produção. Bastaria eu inserir uma outra URL,
por exemplo, - url: google.com, e descrição seria description: API de Prod.
Então eu posso hora fazer uma requisição para saber de nossa API de produção, hora para API de
teste.
[02:58] Vou retirar a "API de Prod", para não acabar fazendo requisição para o local errado. O
Editor me mostra que eu ainda tenho erros, eu não tenho todas as informações necessárias, mas,
teoricamente, eu já tenho suficiente para realizar uma requisição. Então vamos ver o que acontece
quando eu aperto "F12" ou eu venho, em qualquer lugar da página, e clico "Botão direito >
Inspecionar” e seleciono a aba "Networks".
[03:26] Quando eu clico no botão "Execute", ele faz uma requisição para a nossa API de
especialidades, eu abrir a requisição em uma nova aba, espera um pouco que ele está autorizando.
Vamos ver, eu suponho que eu coloquei o link errado, deixa eu dar uma olhada na nossa API de
especialidades. Vou colocar a URL correta "-url: http//6096015d116f300174b29bb". Agora sim, eu
copiei o link do projeto, era isso que estava errado, eu copiei o servidor errado.
[04:04] Agora sim, vamos executar, ele está fazendo uma requisição que está carregando, e vamos
ver porque que não funcionou de novo. Vou executar e ver o que está acontecendo, ele está fazendo
a requisição. Ótimo, ele devolveu algo, perfeito, a requisição foi feita, e por que ele não colocou
nada para nós?
[04:21] Vamos fechar a aba "Inspecionar" e recapitular tudo. O que acontece com essa interface, o
que ele está fazendo? Quando eu tenho um path e tenho todas as informações dele, o próprio
Swagger consegue realizar uma requisição de teste, e ele realmente está fazendo essa requisição.
Tanto é que quando eu abri a aba de redes, a requisição foi feita para o local correto, devolveu as
respostas corretas.
[04:47] Eu ainda tenho erros aparecendo na minha tela, então isso, muito provavelmente, está
impedindo o Swagger de exibir a resposta para nós. Porque ele não sabe o que exibir, ele não sabe
se ele pode exibir tudo, se está tudo correto. Ou seja, ele não sabe que ele precisa parsear aquele
Json e exibir na tela, por exemplo.
[05:05] Então o que precisamos fazer agora, que exatamente o erro que está aparecendo no Editor.
Eu preciso informar quais são as possíveis respostas desse end point. Se, por exemplo, tiver um erro
no meu banco de dados eu respondo com o status 500, em caso de sucesso eu respondo com status
200, posso colocar até exemplos de resposta. Então vamos ver exatamente como conseguimos
definir uma resposta.
Possíveis respostas
[00:00] Bem vindos de volta. Vamos definir as possíveis respostas desse path* ou end point. Eu vou
adicionar o responses:, um objeto, onde a chave é o status possível. Então, imagine que em
caso de sucesso, eu tenho 200. Dentro dessa chave eu posso ter a descrição desse status, então, por
exemplo, description: Sucesso, ou algo do tipo.
[00:30] Ainda, eu posso ter o conteúdo content:. Então vamos descrever esse conteúdo, o
conteúdo pode ser em vários formatos. Logo, a chave do conteúdo é o formato, por exemplo,
escrevo application/json:. E o valor é o conteúdo em si, posso ter então em Json, XMIL,
texto puro, HTML e outros. Como eu posso descrever essa resposta?
[00:54] Eu posso dar um exemplo, adicionar um texto puro mesmo, colocar mais de um exemplo.
Mas o que eu vou fazer é definir um esquema adicionando a chave schema:, ou seja, vou informar
qual é o tipo de retorno. Por exemplo, aqui o tipo vai ser objeto, type: object.
[01:12] Esse objeto ele tem propriedade, escrevo properties:. Então posso definir para ele uma
série de propriedade. Reparem que quando definir o responses a minha resposta já apareceu no lado
direito da tela. Voltando as propriedades, eu vou ter uma propriedade chamada id:, essa ID tem
como tipo type: integer, ela é do tipo inteiro.
[01:34] Também vou ter uma propriedade descrição:, onde o tipo é um string, type:
string. Teoricamente eu tenho um esquema bem formatado, então vamos recapitular o que eu
escrevi antes de vermos como ele vai aparecer. Eu tenho um path de especialidades, onde se eu fizer
uma requisição get para especialidades, ele vai recuperar todas as especialidades e respostas
possíveis no status 200.
[02:03] Repare que só essa resposta possível, onde a description é no caso de sucesso, eu posso
colocar ou não essa descrição, normalmente colocamos. E eu posso informar qual é o conteúdo, ou
não, talvez eu não precise informar, mas dessa vez eu quero informar. O conteúdo devolvido é em
Json, ou seja, isso é o formato, é um mine type. Eu poderia ter Text, HTML, ou alguma outra coisa,
Text Plain se fosse um texto puro, mas eu vou querer Jason.
[02:32] Eu posso definir ou exemplos de como isso vai retornar, ou um scheme, um esquema de
como isso vai ser e através desse esquema o próprio Swagger pode montar exemplos para mim.
Então como esse esquema? Ele poderia ser um a única string, poderia ser uma inteira, mas nesse
caso vai ser um objeto.
[02:50] E quais são as propriedades desse objeto? ID, que é do tipo inteiro, e descrição que é do tipo
string. Com isso definido, vamos ver como fica, repara que eu poderia ter várias respostas para os
parâmetros, mas eu tenho uma só. Onde o código é 200 e descrição é sucesso. Posso ainda ter vários
media types, vários tipos dessa resposta.
[03:10] No meu caso eu tenho apenas o application/json como media type. Com o scheme que
adicionamos o Editor ele já monta um valor de exemplo, e eu cometi um errinho, defini como se o
retorno fosse um objeto, quando na verdade é um array. Então vamos modificar, na verdade, o
type: array, onde items: type: object e as outras propriedades são essas.
[03:42] Agora que está tudo certo, agora é um array, onde cada item desse array tem ID, que um
inteiro, e descrição que é uma string. Agora, com essa resposta mapeada, o que eu vou fazer é tentar
executar essa requisição de exemplo. Depois que eu o executo, nos mostra o comando que eu
poderia executar usando o “curl” para fazer essa reposição, qual é a URL efetiva que ele fez
requisição, e a resposta real.
[04:15] Então eu tenho o ID 1 e a descrição desse ID, dessa especialidade é teste, ele mostra
também os cabeçalhos dessa resposta, tudo funcionou. Conseguimos diretamente do nosso Swagger
UI, que está dentro do Swagger Editor, fazer uma requisição real para nossa API. Não só
conseguimos documentar, mas podemos fornecer um ambiente de teste para a nossa API.
[04:41] Já definimos as respostas, definimos como esse dado volta do Servidor, mas conseguimos
definir como enviar informações para o servidor. Através de parâmetros, ou até no corpo dar
requisição. Então vamos conversar um pouco mais sobre isso nos próximos vídeos.
Parâmetros na requisição
[00:00] Bem vindos de volta. Então já sabemos como definir um path, ou endpoint, já sabemos
como definir o que ele traz de volta para nós. Agora vamos definir o que podemos mandar para eles.
Se dermos uma olhada na nossa MockAPI, quando eu clico em "Edit" a especialidade, eu tenho a
opção de enviar um ID para especialidades.
[00:25] Para essa URL eu posso colocar "/especialidade/1", e ele vai trazer somente a especialidade
com o ID 1. Então vamos definir exatamente isso, para podermos enviar esse parâmetro. Lá no final
da página do Editor eu vou inserir um novo path, usando as especialidades/, e eu preciso
informar que nessa parte da URL vai ser um parâmetro. E para informar que é um parâmetro eu
coloco entre chaves {id}, chamando de ID.
[00:53] Posso chamar do que eu quiser, por exemplo, especialidadeID, alguma coisa assim,
mas eu vou chamar só de ID. Vamos lá, eu quero mapear uma requisição adicionando o verbo get.
Dentro dessa requisição get aquela mesma história eu posso ter um sumary: Recupera uma
entidade pelo ID.
[01:13] E eu posso ter as responses, mas antes de ter as respostas eu quero mapear esse parâmetro
ID, que o primeiro erro que está aparecendo para mim. Esse parâmetro ID que foi declarado, ele
precisa ser definido de alguma forma, ou dentro da aplicação toda, ou dentro desse path.
[01:30] Então vamos lá, eu vou informar que eu tenho parameters:. Essa chave parâmetro ela é
um array, no quadro a direita “precisa ser uma array”. Para definir um array o que eu posso definir
no parâmetro o nome dele e tem que ser exatamente o que tá aqui no URL, então no caso é ID, eu
preciso informar onde esse parâmetro ID vai ser enviado.
[01:57] Esse parâmetro ID eu sei que ele vai ser enviado direto na URL no path, porque ele está já
está definido. Então vou colocar abaixo no nome, in: path. Só que existem outras
possibilidades, por exemplo, se ao invés especialidades/id, fosse /especialidades/id/1, com uma
query string eu colocasse que o ID é 1, ao invés de fazer especialidade/1, se fosse naquele outro
formato eu poderia colocar aqui uma query e remover esse parâmetro iddaqui, mas não é o nosso
caso, realmente vai ser no path.
[02:32] Eu posso adicionar algumas outras informações como, por exemplo, colocando o schema,
então aqui eu vou definir o type: integer, e esse tipo é um inteiro, ou seja, o ID precisa ser
um número. Eu preciso informar se este parâmetro é ou não obrigatório, no nosso caso como ele tá
na URL, eu preciso passar ele.
[02:51] Então required: true, ou seja, verdadeiro, eu preciso informar esse parâmetro. Tendo
definido como eu envio esse parâmetro, se eu dou uma olhada no nosso Swagger UI, quando eu for
enviar essa requisição eu posso adicionar a informação de ID nela. Mas antes vamos colocar as
respostas possíveis.
[03:16] Volto ao Editor, dou um "Enter", e adiciono "responses:", com aquele esquema. Eu posso ter
uma resposta de sucesso que vai ser assim desciption: Sucesso, com nesse caso foi sucesso.
Ainda temos o contente que é um application/json:, então sempre respostas dessa API
vão vir em Json.
[03:36] Da mesma forma como fizemos anteriormente, eu posso adicionar um schema:. Então
vou pegar isso daqui do nosso path. Porque não vou retornar o array, somente o objeto direto.
Repara que eu já tenho uma resposta em Json, no caso de sucesso, trazendo um ID e uma descrição.
[03:59] Então eu posso testar essa requisição, eu vou buscar a especialidade com ID 1, quando eu
executo no Swagger UI, se eu não fiz nenhuma besteira. A requisição feita corretamente e tá
devolvendo a requisição com o ID 1, e tem a descrição teste. Mas repare que nas respostas
possíveis, eu só tenho um caso de sucesso, e se eu passar o ID errado? Se eu passar o ID errado eu
já sei o que vai acontecer.
[04:24] Então primeiro eu vou descrever, caso eu passe o errado eu vou ter um cenário de 404. E a
descrição para isso eu vou dizer que é description: Especialidade não
encontrada. O conteúdo dessa resposta um pouco diferente também, vai vir com o cabeçalho
informando um application/Json, mas, na verdade, eu nem preciso de um schema.
[04:51] Eu posso ter se eu quiser, mas, na verdade, eu já vou colocar um example, porque ele vai
retornar a mensagem example: “Not found”. Como isso vai ser exibido, deixa eu fazer um
clear, para limpar aquela resposta que já veio. Então, de novo, eu tenho aqui um possível ID para eu
passar e as possíveis respostas são 200 em caso de sucesso, e 404 no caso de especialidade não
encontrada.
[05:13] O valor retornado vai ser um string Not found. Então eu posso na barra de busca do UI e
tentar buscar “especialidade dois”, por exemplo, que eu sei que não existe. Quando eu executar a
resposta exatamente o que eu disse, Not found, esse é o corpo da resposta. O código é 404 e tem o
content - type: json, então mapeamos corretamente.
[05:36] Então reparem que nós fizemos duas coisas nessa aula, nós mapeamos um parâmetro, ou
seja, nós podemos enviar um parâmetro para nesse específico get de /especialidades/{id}/, podemos
passar esse parâmetro. E esse parâmetro tem que ser um inteiro e é obrigatório.
[05:53] “Ah Vinícius, eu poderia colocar esses parâmetros fora da minha operação *get, poderia
colocar aqui direto aqui fora, se eu copiar aqui para fora, isso aqui daria um erro?”
[06:10] Vamos ver o que acontece, isso não veio. O que vai acontecer agora é se eu tiver alguma
requisição além do verbo get. Se eu tiver, por exemplo, algum put ou post it, eu já vou ter as
definições desse parâmetro ID definidas corretamente.
[06:24] Então deixa eu limpar a execução e eu continuo conseguindo passar o parâmetro
corretamente, ele busca corretamente. Só para você entender um pouco melhor o que isso quer
dizer. Se eu tiver além de uma requisição do tipo get, alguma outra requisição para
especialidades/id, eu não preciso de novo repetir essa definição do parâmetro.
[06:45] Eu posso simplesmente definir esse parâmetro para todos os verbos que forem feitos nesse
path, nessa URL. Então essa é a diferença entre colocar direto na “especialidades”, no mesmo nível
que todos os verbos. Ou colocar dentro de algum verbo, se eu colocar como estava antes, dentro do
get. Significa que se eu tivesse um put, por exemplo, eu teria que definir esse parâmetro de novo.
[07:12] Agora nesse caso como eu fiz agora pouco, para todos os verbos que eu definir esse
parâmetro já vai estar definido. Então recapitulando, nós aprendemos três coisas, na verdade, como
definir um parâmetro, seja para um end point específico ou para um verbo específico. Aprendemos
também a como definir mais de uma resposta, inclusive, não só com um schema, mas também com
o example.
[07:40] Ou seja, além de definir o esquema, o que vem, um objeto, eu posso direto dar um exemplo
de como ele virá. Então dessa forma conseguimos definir essa resposta. Agora não só parâmetros
podemos enviar para lá, imagina que eu queria cadastrar uma nova especialidade.
[07:59] Então quero fazer uma requisição post para a barra especialidades. Eu preciso enviar algo
no corpo da requisição, então essa parte um pouco mais complicada, vamos ver como definimos o
corpo de uma requisição do próximo vídeo.
Dados no corpo
[00:00] Bem vindos de volta. Vamos definir um cenário onde consigamos cadastrar uma nova
especialidade. Nós temos duas URLs por enquanto, barra especialidades e especialidades, barra
alguma coisa. Então a URL para eu cadastrar algo também é barra especialidades, não uma URL
nova, como barra especialidades, barra nova, ou algo do tipo.
[00:28] Então o que eu vou fazer é definir um novo verbo dentro desse mesmo path. Então vamos
definir um post:, através do verbo post eu consigo criar uma nova especialidade. Eu posso
adicionar as mesmas informações, como, por exemplo, sumary: Criar nova
especialidade. Posso utilizar o sumary para informar o que esse end point faz.
[02:49] Se não escrevi nada errado, ele já mostra um valor de exemplo, então descrição e alguma
string, e me mostra também o schema. Então, se eu não fiz nenhuma besteira, já consigo realizar
essa requisição.
[02:59] Então vamos testar, no corpo ele já preenche para mim esse Json, com um valor de
exemplo, eu vou colocar no corpo uma "nova especialidade". Vamos realizar essa requisição e ver
como vem resposta, se a resposta vai chegar, mesmo sem ter definido o schema, vamos ver o que
acontece. Quando eu executo ele mostra de novo seu URL completo, aparentemente tudo bem, e
realmente ele devolveu um 201 e o corpo é um objeto do tipo especialidade.
[03:33] Ou seja, ele traz para nós o ID e a descrição. Então podemos colocar aqui, vamos aproveitar
a informação que temos agora para colocar o nosso contente com o
application/json:sendo esse schema: aqui. Eu posso copiar o type: object com as
propriedades lá do nosso path. O tipo é um objeto e as propriedades são essas. Então agora deixa eu
limpar essa busca que eu fiz e tenho a resposta correta.
[04:10] Então dessa forma conseguimos descrever como é o corpo de uma requisição, como o corpo
de uma requisição precisa ser e, inclusive, acabamos de fazer um post. Ou seja, nós criamos uma
nova especialidade, se eu vier e buscar todas as especialidades, eu espero que venham duas agora.
Apareceu a descrição teste e a descrição nova especialidade.
[04:34] Então com isso, já conseguimos definir como enviar informações para o servidor, seja com
parâmetros, como nós vimos, que pode ser do path, na query, no header ou em cookie. Vimos como
enviar um requestbody, ou seja, mandar dados no corpo da requisição. Agora eu vou deixar um
desafio para você, já tenho o get, tenho post, faltam só dois verbos para completarmos o crude da
especialidade.
[05:07] Então com o que temos, você já consegue fazer o put e o delete, como que isso vai ser?
Deixa-me te explicar o que você vai fazer. Em especialidades já conseguimos criar uma
especialidade e buscar todas. Já em especialidades/id conseguimos buscar uma, atualizar a
especialidade em questão e remover uma especialidade.
[05:30] Então, além do get, você vai adicionar o post e o delete, vai fazer alguns testes, verificar o
que é necessário para você realizar suas requisições. Sempre crie uma especialidade e depois tente
remover, ver o que é necessário. Crie uma nova especialidade, tente atualizá-la, ver o que é
necessário enviar. Dessa forma você vai chegar na documentação.
[05:54] Caso, por algum motivo, você não consiga, o fórum está aberto e eu vou tentar te ajudar,
mas com o conhecimento que já temos, é possível documentar essas duas novas operações. Agora
que já estudamos muitos conteúdos, vamos sair um pouco desse comum e ver como melhorar o que
já temos.
[06:12] Por exemplo, reutilizar essa definição de uma especialidade, porque temos o type object
sendo repetido em muitos lugares. Enfim, podemos fazer bastante coisa ainda, vamos ver o que
mais podemos definir com o Swagger a partir do próximo Capítulo.
Definindo tipos
[00:00] Boas-vindas a mais um capítulo do nosso treinamento. Nós estamos documentando uma
API utilizando Swagger. Então já fizemos bastante coisa e a documentação está bastante funcional,
eu diria até que ela está bem completa. Só que agora eu posso facilitar um pouco nossa vida,
porque, por exemplo, o pedaço de código abaixo está sendo repetido em muitos lugares.
[00:20] Então podemos melhorar isso criando esquemas em um lugar separado, chamado
componentes, ou components. Vou fechar a chave de paths e tudo mais que temos, clicando na
flechinha ao lado da chave. Agora o que eu quero adicionar é "components:", que é um objeto.
Dentro dele eu posso adicionar schemas, respostas, parâmetros, exemplos, corpos, cabeçalho,
enfim, muitas coisas.
[00:56] Mas o que eu quero adicionar é um schema. Esse schema tem como chave um nome e
depois todas aquelas informações do tipo, se é um objeto ou não. Então, antes de qualquer coisa,
vamos definir um tipo bem simples. Imagine que ao invés de ter o ID como um inteiro, eu queria
criar um tipo ID.
[01:17] Posso fazer da seguinte forma, eu vou chamar de Id:, e esse ID pode ter várias coisas
como um type: integer, por exemplo. E está aparecendo um erro no meu documento porque
esse ID não está sendo usado em nenhum lugar, mas se olho aqui em baixo eu já tenho essa
definição, repara um ID como inteiro.
[01:36] Posso ter um título, por exemplo, title: "Id", e eu posso ter uma descrição
description: "Identificador único de alguma coisa", de alguma
especialidade ou algo assim. Então podemos ir adicionando informações nessa chave e eu posso
colocar, por exemplo, quantos caracteres esse ID pode ter, se fosse uma string, mas no caso é um
inteiro, posso definir o valor máximo ou mínimo. O valor mínimo é um, não posso ter um inteiro
menor que um.
[02:07] Eu posso ir adicionando informações a esses componentes, a esses schemas. Então se eu
consigo criar vários tipos, eu consigo criar um tipo chamado especialidade. Vamos fazer exatamente
isso no próximo vídeo, vamos criar o nosso tipo especialidade, para que não precisemos ficar
fazendo todo esse trabalho.
[02:28] Nas propriedades do schema eu tenho o esquema object e todas as propriedades. Aqui em
cima eu também tenho o type object com as propriedades, e depois na resposta tem o type object
com as propriedades. Então vamos fazer exatamente isso, vamos pegar o schema, vamos criar esse
schema para não precisar ficar repetindo esse código em outros lugares.
Definindo objetos
[00:00] Bem vindos de volta. Já sabemos como definir um tipo, se você ainda não fez isso, pausa o
vídeo agora e define o tipo de especialidade, depois volta e ver se fizemos igual. Para você poder
praticar, porque com os conhecimentos que temos, teoricamente, já conseguimos fazer. Então
pausou, voltou e eu vou fazer com você.
[00:22] Eu não vou ter mais o tipo ID, porque ele não está trazendo valor nenhum para nós. Vou ter
um tipo chamado Especialidade, esse tipo especialidade não é um inteiro, ele é objeto ele não
tem esse título, ele não precisa dessa descrição. Se eu quiser posso colocar, mas ele não tem. E ele,
obviamente, não tem valor máximo ou mínimo.
[00:40] O que ele tem é propriedades. Então vou definir as propriedades do meu tipo especialidade,
ele tem um ID que tem como tipo um inteiro, id que tem type: integer. Também tem uma
descrição que tem como tipo uma string, descricao: que tem como tipo type: string.
[01:00] Inclusive em uma string, poderíamos colocar um formato, por exemplo, se é uma data
format: date-time. Mas no nosso caso não é nada disso, é realmente só uma string. Então
não preciso de formato, mas acho válido citar.
[00:01:16] Tenho meu schema definido então, teoricamente, isso já nos mostra um ID que é um
inteiro, e uma descrição que é uma string. Agora o que nós temos é um componente definido, nós
temos um esquema definido, fora de qualquer operação, fora de qualquer path, fora de qualquer
coisa.
[01:35] O que eu quero fazer agora pegar o esquema, essa especialidade e utilizar em algum lugar.
Mas, por enquanto, ainda não sei como fazer isso. Então vamos para recapitular o que fizemos na
parte de definição, temos fora de qualquer objeto, nós temos a possibilidade de definir
componentes.
[01:56] Um dos componentes possíveis é o esquema, se eu tiver alguma resposta que é sempre
devolvida igual. Por exemplo, se sempre que eu cadastrar uma especialidade, aparece uma
especialidade sem o ID, e sempre que eu atualizo também vem sem o ID, eu posso definir um novo
esquema.
[02:16] Ou melhor, eu posso definir direto a resposta, então se sempre que eu insiro uma
especialidade, ele devolve uma especialidade inteira. Quando eu busco especialidade, ele também
traz de volta especialidade inteira. Eu posso definir essa resposta responses:. Inclusive posso
dar um nome para essa resposta como, por exemplo, Especialidade também.
[02:37] Dentro dessa chave você vai definir as informações dessa especialidade, da mesma forma
como definiríamos uma resposta. Então um componente é algo que a gente pode reutilizar em
vários lugares. Eu não vou definir essa resposta, eu vou deixar como desafio para que você defina.
Porque o que eu quero fazer agora é, de alguma forma, agora entendemos o que é um componente
que é "qualquer coisa que eu possa reutilizar em vários lugares".
[03:02] Quero saber como efetivamente reutilizar, eu quero pegar essa especialidade e utilizar.
Reutilizar ela em todas as chaves que contém ID no meu documento, ou seja, pegar aquele
componente fazer o uso dele em vários lugares, e é exatamente isso que vamos fazer no próximo
vídeo.
Referenciando tipos
[00:00] Bem vindos de volta. Agora o que eu quero fazer é pegar algo que eu definir nos
componentes e referenciar em outro lugar. Por exemplo, nas minhas respostas ou até no corpo, se
fosse o caso, em um request body. Vamos começar onde eu tenho um array e dentro de items eu
posso ter esse objeto, que a especialidade.
[00:23] Em algum momento eu quero referenciar um componente, posso utilizar uma propriedade
chamada $ref:". Essa propriedade chamada ref é uma string, então posso colocar entre aspas.
Qual o formato dela? Eu começo com hashtag para indicar a raiz desse documento, como estou na
raiz desse documento, eu posso acessar os componentes.
[00:50] Dentro dos componentes eu posso acessar os schemas, e dentro de schemas especialidade,
então "$ref: "#/components/schemas/Especialidades"". Então, teoricamente, agora na minha
resposta de Especialidades tenho aqui como resposta possível aquele mesmo array. Logo, o meu
esquema é um array de especialidade, aparece os colchetes indicando um array e dentro deles a
Especialidades.
[01:15] Vamos fazer exatamente isso para os nossos outros cenários onde utilizamos esse mesmo
tipo. Reparem que aqui não temos uma especialidade, porque não é um ID e uma descrição, temos
apenas a descrição, então não conta.
[01:33] Já na resposta podemos utilizar, podemos trazer esse ref aqui. Então vamos ver se eu
coloquei no local correto, isso aqui é a resposta do meu post, então a resposta do meu post está
certo, está lá como Especialidade.
[01:46] Vamos ver onde mais eu posso colocar, aqui, nessa resposta do meu especialidades/
{id}. Também posso colar esse ref, então no especialidades/{id} a resposta está certa, aparecendo
como um array, temos um esquema trazendo uma especialidade. Então repare que dessa forma
conseguimos reutilizar código na nossa documentação.
[02:09] Se em algum momento, por exemplo, essa resposta existe em muitos lugares, então aqui em
responses eu tenho sempre um 200 quando o script no sucesso, e o conteúdo é sempre um
applicationjson que o schema é essa referência?
[02:22] Você pode colocar nos componentes a mesma response. Então, de novo, eu vou deixar
como desafio, eu não vou implementar isso. Porque eu quero chamar atenção para um detalhe
fizemos, contudo, eu não expliquei muito. No próximo vídeo eu volto para falar sobre arrays.
Definindo arrays
[00:00] Bem vindos de volta. Esse vídeo também vai ser bem curtinho, só para explicar um detalhe,
algo que eu fiz, mas acabei não explicando muito bem. Nós podemos ter diversos tipos de dados,
podemos ter integer que é um inteiro, number que é algum número diferente de inteiro, string que
pode ser um texto qualquer, uma data, data e hora.
[00:21] Podemos ter object, que são várias propriedades, ou seja, uma chave mapeada para um
valor, uma chave uma mapeada para um valor. E podemos ter array, que é um conjunto de algum
desses outros dados. Temos também o booleano, verdadeiro ou falso.
[00:36] Então definimos um array no nosso documento e não falou muito sobre ele. Vamos definir
alguns componentes teste, por exemplo, uma String: que é do tipo type: string ela pode
ter como format: date-time. Esses tipos representam uma data ou uma data e hora.
[01:04] Nós temos números Number: que é do type: number onde o formato pode ser float
ou decimal. Float é um tipo de é número flutuante, ou decimal que é um pouco maior vamos
dizer assim, algo que tem mais precisão.
[01:24] Agora quando falamos de array, deixa eu remover o que acabei de fazer, temos um detalhe
de interessante que já fizemos e é bastante simples. Então vou chamar de especialidades no plural, o
tipo array ele não possui propriedades, não possui formato, o que ele possui é items, ele tem aqui os
itens. A partir desse detalhe de itens, eu posso informar o tipo dele, por exemplo, eu posso informar
título, todas as restrições que eu poderia em qualquer outro esquema.
[01:58] Então posso indicar que ele é type: object e tem as properties: de uma
especialidade. Ou eu posso vir aqui e fazer um $ref:
“#/componentes/schemas/Especialidade”. Então se eu tenho especialidades, significa
que é um array de especialidade. Ele é um array de ID e de descrição. Lá naquele momento que
usamos array eu posso agora fazer um diretamente esse ref aqui. Porém, ao invés de ser
especialidade, vai ser de especialidades, no plural.
[02:37] Então deixa eu voltar na minha primeira definição de especialidade e o nosso example
continua igual. Então essa aula foi só para entendermos um pouco melhor sobre os tipos, e vou
deixar um "para saber mais" com todas essas definições de cada um dos tipos, mas era
principalmente para entendermos o que fizemos na parte de arrays.
[02:57] Porque quando eu tenho um tipo array eu preciso definir quais são os itens que vão estar
dentro desse array. Que pode ser desde qualquer coisa, até outro esquema nosso mesmo.
Conseguimos filtrar bem o que pode ter dentro de um array.
[03:14] Falamos bastante sobre esses componentes, definimos esquemas, já sabemos até como
reutilizar respostas e fica aí o desafio. Agora vamos ver o que mais podemos colocar nesses
componentes que não trabalhamos ainda. Que inclusive, já dando spoiler, é algo que nem iremos
utilizar em nossa API, mas é de extrema importância sabermos como fazer para APIs do mundo
real. Então vamos falar um pouco sobre segurança.
Security schemes
[00:00] Boas-vindas a mais um capítulo desse treinamento de Swagger. Agora descreveremos algo
que nem vamos utilizar nessa API. E não vamos utilizar porque, por ser uma API de teste, que eu
criei com o "mockapi.io", ela não exige autenticação. Mas a maioria, senão todas as APIs que
desenvolvemos, precisam de algum processo de autenticação, às vezes até de autorização.
[00:25] É muito comum precisarmos, por exemplo, gerar um token, e a partir desse token, fazer as
próximas requisições. Então, escreveremos isso agora, vamos descrever como essa autenticação é
feita, ou seja, se é utilizando um token, se é uma API key, ou algo do tipo.
[00:45] Depois, como que protegemos algum end point para que ele só seja utilizado, para ele só
seja acessado, depois termos a autorização. Vamos começar definindo esse esquema de segurança,
além de termos esquemas, além de termos respostas, podermos ter security schemes, ou seja, os
nossos esquemas de segurança.
[01:06] Eu posso dar qualquer nome para os meus esquemas, então vou chamar esse esquema de
auth, mas pode chamar de qualquer coisa. Esse meu esquema ele precisa ter algumas informações
como, por exemplo, ele vai ser uma API Key, ou seja, é só uma chave de API que eu forneço para
meu cliente, ele vai ser através de um token gerado pelo servidor, então ele será enviado por HTTP
de alguma forma.
[01:30] É através de Oauth, a forma como vamos fazer. Então eu vou definir como se a nossa API
estivesse utilizando um token, ou seja, JWT ou alguma outra coisa é semelhante. Porque, pela
minha experiência, é o mais comum, é o que iremos mais utilizar, é o que eu sempre utilizei. Para
definirmos um tipo de autorização usando o token, iremos colocar type: http. Ou seja, essa
informação de segurança enviada através de HTTP.
[02:00] Além disso, eu preciso definir o esquema, mas não esquema como estamos definindo até
hoje, e sim o esquema HTTP dessa informação. Eu não vou entrar em detalhes sobre o que é um
esquema HTTP de autorização, mas existem basicamente alguns tipos de token, o tipo mais comum,
é o tipo de token em que enviamos informando que nós somos os portadores aquele token.
[02:24] Ou seja, eu envio meu token dizendo," Olha só esse token é meu, então eu estou em
autorizando. Como se eu estivesse fazendo login, eu estou te dando minhas informações para você
garantir que eu sou eu."
[02:35] Então esse tipo de token é o que chamamos de bearer, adicionamos scheme:bearer, ou
seja, esse token é um portador. De novo, é como se fizéssemos login, e um processo real, eu vou até
deixar um "para saber mais", sobre como foi processo de autorização por token e depois de um
exemplo com JWT. Mas basicamente como funciona, temos uma URL barra login, barra out e mais
alguma coisa.
[02:58] Onde enviamos os nossos dados, do nosso usuário e senha, por exemplo, e esse endpoint
devolve um token, usando JWT, por exemplo. E agora para todas as outras requisições, para
gestantes que precisam que eu esteja logado, eu não vou mais mandar o meu usuário e senha, eu não
preciso.
[03:14] Eu vou mandar esse token, e lá no servidor quando eu receber essa requisição, verifica se
esse token está correto, se ele é válido, se é realmente de quem ele diz ser e, a partir disso, autoriza a
requisição.
[03:28] Então dessa forma conseguimos autorizar requisições, e reparem que, após definir esse
esquema de segurança, aparece no SwaggerUI um botão “Authorize”, ou seja, posso liberar o uso
dessa API. Poderia clicar nesse botão “Authorize” e definir o valor para esse token. “Vinicius, que
valor é esse?” É o valor que a API, depois que eu fizesse login, me devolveria.
[03:50] Nesse caso, eu vou botar um nome de "teste", porque, de novo, na nossa API não estamos
utilizando isso, não precisamos de autenticação. Em uma API real, você enviaria seu usuário e
senha para algum endpoint barra login, por exemplo, e ele devolveria com um token e esse token
você colocaria nesse campo. Então quando eu clico em “Authorize”, ele simplesmente vai
armazenar esse token.
[04:13] Agora o que ele vai fazer? Se em alguma requisição, se em algum path desses eu informar
que esse path precisa de autorização, então ele vai enviar esse token que salvamos. “Vinícius, e
como informamos que determinado path precisa dessa autorização ou não?” É exatamente isso que
veremos no próximo vídeo.
Para saber mais: Tokens
Autenticação por token é um conhecimento mais do que necessário quando se trata de
desenvolvimento de APIs. Vou deixar aqui 2 vídeos para explicar melhor o funcionamento desse
tipo de autenticação:
Parâmetro security
[00:00] Bem vindos de volta. Vamos entender como podemos informar ao Swagger que sempre, por
exemplo, que eu tentar acessar todas as especialidades, ele precisa mandar aquele token. Podemos
fazer isso através de uma chave na nossa definição. Logo após responses, eu vou adicionar
security:.
[00:24] E em security eu posso definir diversas formas de autenticação, que ele aceita. Uma delas,
que vai ser com o nome que já definimos anteriormente que é auth:. Então se eu tivesse colocado
ali calopsita, em security eu colocaria calopsita também, mas no nosso caso é auth. E isso é um
objeto, então a chave é o nome que já definirmos e o valor é um array.
[00:47] Esse array só é utilizado se eu tivesse a minha forma de autenticação for por Oauth, método
de autenticação normalmente usados quando integramos com serviços externos, mas pode ser
utilizado só pela API também. Porém, ele é um pouco mais complexo, então não vou entrar em
detalhes agora.
[01:05] Mas como estamos utilizando outro tipo de autenticação, através de tokens, que é uma
autenticação HTTP, eu vou simplesmente deixar o array vazio. Com isso, o que vai acontecer? Vou
vou abrir o meu inspecionador de elementos, vou inspecionar alimentos, vou vir aqui em
“Network”, está tudo vazio. Agora repara que aparece um cadeado ao lado das minhas
especialidades, isso significa que quando eu fizesse a requisição eu preciso estar logado. Ou seja,
meu authorize precisa ter algum token.
[01:39] Quando eu fiz essa requisição o que o Swagger vai fazer, ele vai enviar um cabeçalho
authorization com o valor barier e o valor do meu token. Então quando eu fizer o teste, quando eu
executar, na opção request header do meu inspecionar, eu tenho um cabeçalho authorization com o
valor barier, que aquele scheme do token. Ou seja, o skimmer dessa forma de autenticação.
[02:11] Que pode ser basic, que não é através de token, é através de usuários e senha mesmo.
Barier que é através de token, outros schemes HTTP. Mas enfim, eu tenho o meu tipo de token e o
valor do meu token, então dessa forma se a minha API, ele realmente precisasse dessa autenticação,
ela estaria recebendo essa informação.
[02:29] Repare que eu não preciso, deixa eu fechar o inspecionar, especificar na diretamente,
porque minha API já está autorizada, eu já tenho os meus securityschemes definidos. Se eu tenho
um scheme, eu poderia ter essa security não só para um path, mas para várias coisas. Então será que
eu poderia colocar direto na chave path um security?
[02:53] Eu posso, então olha só o que eu vou fazer eu vou adicionar a chave path e apagar esse
security que eu coloquei nas outras chaves. A partir de agora todos os meus end points tem um
cadeado. Então sempre que eu fizer todas essas requisições, o meu token vai ser enviado. E se eu
vier em “Authorize” e fizer log out e fechar, os cadeados agora ficam cinza, ele tá um pouco mais
opaco.
[03:20] Então se eu tentar fazer essa requisição agora, abrindo o meu inspecionar. Se eu tentar fazer
requisição ele não vai enviar esse dado, ele agora só ele não envia o cabeçalho authorization. Se
fosse uma API real que precisa da autorização, iriamos receber como resposta um erro.
[03:35] Dessa forma conseguimos definir autorização, definimos o schema para conseguir realizar
autorizações direto pelo nosso Swagger. E conseguimos definir o end point, a endo point, verbo a
verbo, ou geral para toda a nossa aplicação, que ela vai utilizar determinado esquema de segurança.
[03:54] Agora no próximo vídeo eu quero trazer um detalhe bem pequeno, então o vídeo vai ser
bem curto. Que é uma espécie de auxílio, principalmente para quem tá lendo esse documento. Então
já volto para falarmos um pouco sobre um detalhe aqui no nosso esquema de segurança.
Bearer format
[00:00] Bem vindos de volta. Eu só quero trazer um detalhe bem pequeno que nem interfere na
usabilidade de quem estiver olhando o Swagger UI, mas pode ajudar um pouco em alguns casos,
quando estivermos olhando pelo Swagger Editor. Podemos ter essa autorização HTTP, com esse
scheme, ou seja, utilizando tokens.
[00:20] Com qualquer formato de token, você pode criar o seu formato de token, inclusive naquele
vídeo que eu deixei no "para saber mais" falando sobre autorização por tokens. Comentamos
exatamente sobre isso, sobre a possibilidade de eu criar meu token e utilizá-lo na hora de autorizar
algo.
[00:37] Mas, no nosso caso, nós estamos utilizando um formato específico token, que é o JWT.
Então nós conseguimos deixar claro através do bearerFrotmat:, esse bearerformat podemos
escrever qualquer coisa nele. E essa qualquer coisa serve somente para sabermos o formato desse
token, como a nossa API vai tratar esse token.
[01:02] O cliente nem precisa saber disso, porque tudo que ele vai fazer mandar o usuário e senha,
vai receber um token de volta, independente do formato. E esse token ele tem que mandar nas outras
requisições. Então para sabermos que isso é um JWT, é comum que tenhamos esse bearerformat
com o JWT.
[01:19] Isso é um detalhe a mais para quem está consumindo essa documentação, para quem está
trabalhando com o Swagger Editor. Então repare que essa chave bearerformat não é algo que eu
inventei, é uma chave existente. Justamente para dar esse auxílio para, sabermos com qual formato
estamos trabalhando.
[01:39] Então dessa forma definimos que a nossa autorização é utilizando HTTP, que por padrão, é
enviando aquele cabeçalho authorization. Que o schema dessa autorização é através de tokens, ou
seja, um bearer que informa quem é o portador daquele token.
[01:54] E estamos informando o formato desse token, o formato que o portador do token está
utilizado é o JWT. Então dessa forma a gente completa essa parte de autorização e, talvez, você
esteja se perguntando um detalhe. Eu estou utilizando o Swagger Editor online, na plataforma do
Swagger.
[02:14] O Swagger UI está integrado com o Swagger Editor, como que eu realmente posso fornecer
isso, ou para a minha equipe escrever no Swagger Editor sem ter que utilizar essa plataforma, não
sei se o Swagger está olhando o meu código.
[02:27] E como podemos fornecer Swagger UI para os clientes, sem que eles precisem ver todo esse
nosso código. Então no próximo capítulo vamos fazer, de forma bem simplificada, uma espécie de
servidor para o nosso Swagger Editor e outro servidor para disponibilizarmos o Swagger UI.
INFRA PRÓPRIA
Baixando o editor
[00:00] Boas-vindas a mais um capítulo desse treinamento, onde estamos documentando uma API
existente utilizando o Swagger Editor.
[00:08] E o questionamento levantado no último capítulo foi de que eu estou utilizando esse online
do Swagger, mas se ele sair do ar, ou se eu estiver sem internet, como que eu posso ter esse editor,
ou na minha máquina um servidor da minha empresa. Outro detalhe é como eu disponibilizo o
Swagger UI para os meus clientes, para que eles possam ver essa minha documentação interativa.
[00:31] Então vamos acessar o site do Swagger, "swagger.io" e vamos começar pelos Swagger
Editor. Vamos acessar as ferramentas, ir em “Swagger Editor”, e ao invés de clicar em Live demo,
que estamos utilizando, vamos baixar esse editor, clicando em "Download Swagger Editor". Aqui
podemos fazer o login e utilizar o “SwaggerHub”, ferramenta um pouco mais enterprise que,
inicialmente, é gratuita para pessoas físicas.
[00:57] Vou utilizar diretamente, baixando o Swagger Editor de alguma forma, então, quando eu
clico na opção "Download", sou redirecionado para o GitHub. Aqui sabemos - teoricamente as
pessoas que já desenvolvem sabem - como funciona o GitHub.
[01:13] Eu poderia baixar esse código, ter esse código na minha máquina e subir um servidor web,
porque isso é um projeto web. Como sabemos, é um sistema que está rodando de forma online,
então poderia subir um servidor web.
[01:26] Só se repararmos no arquivo “Dockerfile”, significa que de alguma forma eles usam
Docker, então quando vamos descendo a página, podemos ver como rodar isso localmente, e
podemos fazer através do Docker. Então podemos baixar essa imagem "docker pull
swaggerapi/swagger-editor", ele vai fazer o download, no meu caso essa imagem já está no meu
computador, já está atualizado.
[01:51] E podemos rodar esse comando "docker run-d -p 80:8080 swaggerapi/swagger-editor", ou
seja, rodar esse container e executá-lo, para termos um Swagger Editor na nossa máquina. Não
falei, mas acredito que seja óbvio: para isso tudo você precisa ter o Docker na sua máquina. Caso
você não queira instalar o Docker, de novo, você pode baixar o projeto como um todo e subir em
algum servidor web, sem problema nenhum.
[02:15] Se eu não me engano é um projeto em JavaScript pelo pack de ponto Json e pela
configuração do JavaScript, eu suponho que seja um projeto em JavaScript. Mas continuando, o que
eu posso fazer além de simplesmente inicializar o servidor, eu posso passar algumas informações.
Como, por exemplo, fazer com que ele leia o meu arquivo em Yaml, ou um arquivo Json, para a
partir dele já carregar a definição, e depois eu ir editando.
[02:42] Então o que eu vou fazer, no Swagger Editor, do que eu fiz até agora, eu vou à barra de
ferramentas "File > Save as YAML". Eu já tenho uma pasta, eu já tenho ele salvo inclusive, mas
vou sobrescrever e substituir. Em breve precisaremos dele em Json também então já converter e
salvar como Json, "File > Convert and save as JSON". Eu também já tinha ele, mas eu vou salvar e
substituir.
[03:08] Tenho dois arquivos, “openapi.json” e “openapi.yml”. Eu posso executar o segundo
comando da página do GitHub, ""docker run-d -p 80:8080 -v $(pwd):/tmp -e ...", vou copiar, colar e
editar um pouco ele no Docker. Primeiro eu não vou rodar nesse modo de "-d -p", vou apagar isso,
ou seja, não vou liberar o meu terminal. Porque eu não preciso disso, vou deixar o terminal travado
com ele.
[03:29] Ele vai rodar na porta 80, ou seja, no porta padrão HTTP, só que lá dentro ele vai usar porta
8080, internamente. Ele tá mapeando a minha pasta atual, eu acho que isso é importante. Vou abrir
uma nova guia do Docker, a minha pasta atual possui os dois arquivos que eu acabei de baixar, eu
os salvei dentro de uma pasta Swagger.
[03:49] Ele está mapeando um volume da minha pasta atual, para uma pasta “tmp”, uma pasta
temporária lá no container. E lá no container ele vai tentar carregar o arquivo de Swagger na pasta
“tmp”, com o nome que está no comando. Então vou modificar para esse nome para "opneapi.yml".
Vai rodar um container a parte dessa imagem do Swagger Editor. Dei "Enter", se nada deu errado,
eu posso ir para o meu navegador e digitar "localhost".
[04:29] Ele abriu meu Swagger Editor, caso não abra de cara, tente atualizar a página. Ele abriu
com aquele arquivo já pronto, para podermos editar e fazer o que quiser. Um detalhe chato como,
isso aqui é um projeto web, o que precisamos fazer. Precisamos ir editar, fazer tudo o que precisa
fazer e depois salvar de novo, salvar como Yaml. Mas isso é um trabalho pequeno, não é nada muito
complexo.
[04:51] Se você não precisar dessa plataforma do Swagger Editor, se você só precisa, por exemplo,
modificar um ID, que antes era um inteiro e agora é um flout, ou sei lá, a descrição que antes era um
string agora é um booleano. Se eu quiser fazer pequenas modificações, você pode abrir esse arquivo
com seu editor de texto mesmo, não precisa dos Swagger Editor. Porque ele é um arquivo de texto.
[05:16] Vou interromper meu Swagger Editor. Eu posso ir no Docker, e abrir o arquivo
"openapi.yml", ele é um arquivo de texto, eu posso editar ele tranquilamente por aqui, se eu não
precisar daquela plataforma. E algum editor de código como VS Code, ou PHPStorm, ou Visual
Studio, ou IntelliJ. Algum editor de código, ou IDE vai saber identificar isso como Yaml, talvez
alguns tenham até algum plug in e já até renderizem de alguma forma.
[05:46] Vale a pena dar uma olhada em como você pode digitar isso de forma um pouco mais
simples. Mas, voltando ao assunto, conseguimos facilmente ter um Swagger Editor na nossa
máquina, eu não preciso de internet para isso mais. Porque esse Swagger Editor está rodando na
minha máquina. Então tudo o que eu preciso está aqui, eu posso editar livremente, ver de forma
automática, de forma instantânea isso sendo atualizado, como ficaria no Swagger UI.
[06:14] Com aquele pequeno problema, de ser um projeto web, então sempre que realizar alguma
edição, eu preciso vir aqui e baixar o arquivo de novo.
[06:23] Agora que fizemos tudo isso, agora que já temos o Swagger Editor na nossa máquina,
precisamos falar da parte que é mais importante. Porque editar eu posso tranquilamente acessar um
próprio Swagger Editor online, colar o meu arquivo, fazer as modificações que eu quiser e baixar o
arquivo de novo, nada me impede de fazer isso.
[06:43] Eu posso editar esse arquivo direto pelo meu editor de texto também, nada me impede de
fazer isso. Agora e o meu cliente, a pessoa que vai acessar essa documentação através dos Swagger
UI, ou seja, como que eu tenho o Swagger UI em alguma máquina, para poder disponibilizar
através do meu servidor web, por exemplo. Então vamos agora, assim como baixamos o Swagger
Editor, vamos baixar também o Swagger UI, de novo, usando o Docker, mas no próximo vídeo.
Baixando o UI
[00:00] Bem vindos de volta. Agora que já temos o Swagger Editor possivelmente rodando na nossa
máquina, vamos baixar o Swagger UI, para disponibilizarmos, através de algum servidor web
nosso, ou como preferirmos. De novo, vou usar o Docker para facilitar as coisas, vou em "Swagger
IU”. Mesmo esquema, ao invés de ir ao Live demo, eu posso vir em "Download Swagger UI".
[00:25] De novo, aquele mesmo esquema, eu poderia fazer poderia me cadastrar para acessar o
"SwaggerHub", onde temos alguns recursos a mais, mas eu não preciso disso então eu clico em
"Download" e vou direto para o projeto do Swagger UI no GitHub. Aqui como um projeto,
teoricamente, um pouco mais complexo, a documentação um pouco mais extensa. Mas se eu descer
a página até a parte de instalação, eu tenho também a opção de utilizar o Docker.
[00:46] Então iremos baixar imagem, só que dessa vez, ao invés de Swagger Editor iremos baixar a
imagem do Swagger UI. Como eu já tenho foi rápido, no seu cenário pode demorar um pouco da
primeira vez. Eu poderia subir um container utilizando essa imagem "docker run-d -p 80:8080
swaggerapi/swagger-ui", só que de novo eu já tenho um arquivo, então eu vou utilizar ele. Então eu
posso copiar esse comando "docker run-d -p 80:8080 -e SWAGGER_JSON=/foo ...", e colar no
Docker.
[01:13] Agora vamos entender ele e fazer algumas modificações. Repare que eu preciso informar o
Json, eu preciso informar o arquivo no formato de Json. Eu vou adicionar isso de novo no, “tmp”,
aquele diretório temporário e adicionar openaapi.json.
[01:29] Eu vou criar um volume, do meu diretório atual, (pwd). Ou seja, a parta que estou agora
vai ser mapeada para a pasta temporária, lá naquele container do Docker que vai ser criado a partir
dessa imagem.
[01:41] Então que eu estou fazendo, em “tmp” eu vou ter tudo que eu tenho na minha pasta atual. E
eu tenho o arquivo “openapi.json” na minha pasta atual, então o Docker vai conseguir encontrar o
/tmp/openapi.json, para acessar ele, o Swagger UI vai acessar ele e carregar a documentação a partir
disso.
[02:01] Teoricamente, agora no meu localhost ao invés de ter o Swagger Editor, eu vou ter o
Swagger UI. Então quando eu atualizo a página do localhosto no navegador, eu tenho apenas o
Swagger UI. Ou seja, ao invés de ter um editor, eu tenho só parte que um possível cliente utilizaria.
Então tem toda aquela nossa descrição, tipo e etc., todos os links que adicionamos. E aquela API
que eu posso realmente utilizar, que fazer aqueles testes interativos.
[02:26] Posso fazer o meu login, imagino que o cliente precisa realmente fazer o login, posso
colocar aqui qualquer coisa, porque imagina que isso é um token real. Depois ele pode me mandar
requisições, pode conferir a resposta, copiar o seu URL e analisar tudo com calma, de forma
realmente interativa. Um detalhe que eu não falei, eu vou deixar de desafio para você.
[02:48] Na verdade, eu vou deixar um "para saber mais”, mas eu vou deixar um desafio para você
fazer antes de ler o "para saber mais". Você vai abrir numa janela, um Swagger Editor com a versão
três já, você vai converter para a versão três. E vai dar uma olhada que não tem esse default naquele
padrão deles, ao invés de ser o default ele é separado por categorias.
[03:11] Ou tags. Fica aí o spoiler. Eu vou deixar um "para saber mais" só para você entender como
essas tags são organizadas. Porque é bastante simples, então cobrimos nesse treinamento para não
estender ele demais, mas só um exercício no final para você não dizer que nesse último capítulo não
passei nenhum exercício. Então recapitulando o que vimos nesse capítulo.
[03:31] Podemos ter tanto o Swagger Editor quanto o Swagger UI, na nossa própria infraestrutura.
Seja na nossa máquina local, ou disponibilizado através de um servidor, para que nossos clientes,
para que nossos possíveis clientes, possam acessar essa documentação.
[03:46] Isso pode ser bastante útil, não só para nós desenvolvedores termos acesso a possíveis
endpoints. Mas para a equipe de negócios disponibilizar isso, para um possível cliente, utilizar isso
como ponto de venda, mostrar sobre organização, entre outros. Não quero me alongar, mas vimos
como é tranquilo termos tudo isso na nossa própria infraestrutura.
Conclusão
[00:00] Parabéns!! Chegamos ao final do treinamento sobre Swagger, onde aprendemos como
documentar e até a modelar APIs. O Swagger, portanto, é um conjunto de ferramentas que nos ajuda
a documentar e modelar APIs. Se já temos uma API documental utilizando o Swagger é ótimo. Se
ainda precisamos modelar uma API, podemos, também, utilizar isso para pensar em quais endpoints
utilizar e etc.
[00:27] Então começamos definido informações da própria API, definindo um título para ela, ou
nome, uma descrição, informando a versão. Colocando links externos, como temos de serviço,
documentação externa, licença contato. Então começamos definindo a parte da API em si. Depois
definimos alguns caminhos para podermos acessar de especialidades, sendo para acessar, para
atualizar, para inserir uma nova especialidade, buscar uma só especialidade.
[00:55] E com isso vimos que nós precisamos de algum servidor. Então nós vimos que é possível
ter mais de um servidor, nosso caso é um só, mas conforme fomos evoluindo nós aprendemos a
enviar dados, seja através de parâmetros, ou seja, através do corpo da requisição. Então nós
aprendemos a enviar informações para o servidor e aprendemos a mapear as respostas que vem do
servidor.
[01:19] Falando em mapeamento, conseguimos extrair alguns componentes, temos um esquema de
especialidade para não ficar repetindo esses detalhes em vários lugares da nossa documentação.
Falamos sobre os tipos diferentes que temos, como o booleano, string, inteiro, array, objeto,
número, que não é inteiro.
[01:40] Enfim, conversamos bastante sobre isso e depois chegou na parte de segurança. Como
autenticar, como ter autenticação direto pelo Swagger. Definimos um security scheme utilizando
JHT. Depois ativamos essa segurança em toda a nossa API, nós vimos como ativar em apenas um
endpoint e depois para toda a nossa API.
[02:01] Depois vimos, também, como disponibilizar isso fora do ambiente do próprio Swagger.
Então temos em nossa máquina um Swagger UI rodando, por exemplo, e a partir daqui podemos
acessar todos os endpoint disponíveis em tempo real, ou seja, acessando a API de verdade lá.
[02:18] Isso é bastante útil, não só para a equipe de desenvolvimento, para testar e para saber o que
está disponível. Mas também para equipe de negócios, para usar isso como argumento de vendas.
[02:27] Então é uma ferramenta muito interessante, inclusive no final eu deixei um desafio para
você organizar um pouco melhor. Ao invés de ter o default, colocar uma tag para quando tivermos,
por exemplo, além de especialidades, também os médicos, você pode ter tags, para organizar em
locais diferentes.
[02:45] Enfim tem bastante coisa para estudar sobre as ferramentas do Swagger, mas essa é uma
super introdução para começarmos a utilizar essa ferramenta. Eu quero deixar o último aviso, um
disclaimer. É possível, a partir de um código, termos toda essa documentação. Você pode me
perguntar por que não fiz isso então? Porque eu teria que escolher uma linguagem e, por exemplo,
uma linguagem vai precisar ter annotations.
[03:11] Então, talvez, você tem que misturar código negócio com documentação através de
annotations. Outras linguagens podem precisar de arquivos externos para fazer essa configuração.
Eu não queria passar nenhuma linguagem específica, porque isso vai mudar muito de linguagem
para linguagem e eu, particularmente, prefiro muito trabalhar dessa forma. Com um arquivo de
configuração externa, sem ter nenhuma relação com o nosso código.
[03:34] Quando eu atualizo nosso código faz parte da responsabilidade de uma equipe madura
atualizar documentação também. Então da forma como eu mostrei aqui, é a forma como sempre
trabalhei e como as pessoas que eu conheço, que trabalham com equipe de maduras também
trabalham.
[03:50] Mas chega de falação, espero que você tenha aproveitado bastante este treinamento, se você
tiver ficado com alguma dúvida, alguma questão nesse meio tempo, pode abrir uma dúvida lá no
fórum, que eu tento responder pessoalmente sempre que eu consigo.
[04:02] Mas quando eu não consigo, temos uma grande comunidade de alunos, moderadores,
instrutores e com certeza alguém vai conseguir te ajudar. Mais uma vez parabéns por ter chegado
até o final. Obrigado por me aguentar até aqui e espero te ver em outros treinamentos aqui na Alura.