top of page
  • Foto do escritorRan Isenberg

Documentação da API sem servidor com Powertools para AWS

Escrevendo documentação OpenAPI
Escrevendo documentação OpenAPI

A documentação de API de alta qualidade aumenta a satisfação do cliente, especialmente na arquitetura sem servidor, onde as funções Lambda atendem à API. Documentar essas APIs sempre pareceu escrever um romance com uma caneta de penas. Pelo menos, era o que acontecia até agora, quando o Powertools for AWS lançou seu utilitário de documentação OpenAPI.

Esta postagem apresenta um método para gerar documentação OpenAPI para APIs baseadas em funções Python Lambda, utilizando Powertools para AWS Lambda e Pydantic.


No próximo post, discutiremos como automatizar esse processo e adicioná-lo ao pipeline de CI/CD do serviço como uma porta de entrada para a produção e publicação da documentação.

 

Índice

 

O caso da documentação da API

Quando projeto recursos que exigem alterações na API, eu os documento.

Acredito fortemente na adoção da abordagem API first . Allen Helton , um herói sem servidor da AWS, escreveu um excelente post sobre os méritos da abordagem API-first. Ela permite que seus clientes de API, sejam internos ou externos, desenvolvam e planejem sua integração com sua API sem serem bloqueados até que você publique a nova API. Você envia a eles a documentação da API e os deixa trabalhar.

Uma abordagem API-first significa que para qualquer projeto de desenvolvimento, suas APIs são tratadas como “cidadãos de primeira classe”. - Swagger.io

A documentação da API também é útil para entender a qualquer momento o que seu serviço fornece de cima para baixo. É ótima para integrações futuras, desenvolvimento de novos recursos e integração de novos membros da equipe.

 

OpenAPI - O Rei Padrão

OpenAPI se tornou o formato padrão para descrever APIs.

A especificação OpenAPI (anteriormente Swagger Specification) é um formato de descrição de API para APIs REST. Um arquivo OpenAPI permite que você descreva sua API inteira" - Swagger.io .

É um arquivo simples no formato JSON ou YML que nos permite descrever nossa API REST e seus:

  1. Pontos de extremidade disponíveis

  2. Operações em cada ponto final

  3. Parâmetros de operação - Entrada e saída para cada operação

  4. Métodos de autenticação

  5. Organize os endpoints por tags ou grupos e até mesmo gere uma solicitação de amostra.


Swagger.io é uma ferramenta que permite visualizar este arquivo de documentação.

Você pode ver uma demonstração ao vivo do formato de um serviço fictício aqui , que se parece com isto:

Exemplo de Swagger.io
Exemplo de Swagger.io

Agora que entendemos como queremos documentar nossas APIs, vamos falar sobre como adaptar esse processo às nossas APIs sem servidor apoiadas por funções Lambda.

 

Gerando documentação da API

Vamos abordar vários métodos de geração de documentação de API.

Na minha opinião, o melhor método para gerar documentação de API baseada em Python é criá-la a partir do código de serviço. Eu uso o Pydantic para definir esquemas de entrada e resposta, e ele tem nativamente a opção de exportar os esquemas para um formato OpenAPI, o que é uma grande vantagem no meu livro. Então, a integração com esta ferramenta é necessária para qualquer solução que escolhermos.


A primeira opção vem nativamente do API Gateway.

O API Gateway tem um recurso bacana. Uma vez implantado, você pode exportar a documentação do OpenAPI do console ou via API, conforme descrito aqui . No entanto, não há suporte para Pydantic , e muitos esquemas de detalhes mais finos (entrada/ou saída) não são facilmente configurados, pois você mesmo define o esquema JSON e habilita a validação da solicitação. E, por último, ele não é criado a partir do nosso código de manipulador, mas do código de infraestrutura, que é bom, mas imperfeito.

Então, embora seja um recurso legal, mais é necessário. Vamos rever outro método.


A segunda opção vem de estruturas como FastAPI.

FastAPI é uma estrutura web moderna, rápida (de alto desempenho) para construção de APIs com Python 3.8+ - https://fastapi.tiangolo.com/

A maioria dessas estruturas e ferramentas Python, como FastAPI, Flask-RESTPlus/Flask-RESTx, Django REST Framework e Connexion, são projetadas para criar aplicativos web e APIs que escutam em um soquete para solicitações HTTP recebidas.

Vamos nos concentrar no FastAPI.

O FastAPI suporta esquemas Pydantic para descrever payloads e gerar documentação OpenAPI diretamente do código. Essa abordagem simplifica o processo de documentação e o mantém sincronizado com o código.

No entanto, você está essencialmente executando um servidor web no Lambda que abre um soquete para ouvir solicitações HTTP de entrada, o que o serviço Lambda já faz para você. É uma estrutura baseada em servidor com implicações negativas em uma inicialização a frio, tamanho do arquivo ZIP do Lambda e latência. E embora você POSSA fazer isso, não acho que DEVA.


Na minha opinião, precisamos de um framework serverless nativo para fornecer documentação OpenAPI gerada a partir do código do manipulador. Ele deve ser rápido e corresponder ao modelo de invocação do Lambda e, como tal, não deve abrir sockets sozinho.

Vamos ver como podemos conseguir isso.

 

Documentação OpenAPI sem servidor

Nosso objetivo é gerar uma documentação OpenAPI para uma API serverless que consiste em um API Gateway e uma função Lambda. Definiremos o esquema de payload de entrada HTTP e TODAS as respostas HTTP possíveis: seus códigos e payload JSON completo. Usaremos o Pydantic para definir todos os esquemas.

A documentação do OpenAPI será disponibilizada em um novo ponto de extremidade da API: '/swagger'.

Na próxima postagem do blog, discutiremos a exportação da documentação e a automatização de todo esse processo.

Agora que entendemos o objetivo, vamos escrever algum código.


Introdução ao Powertools EventHandler

Usamos a biblioteca Powertools for AWS Lambda . Powertools for Lambda é a biblioteca serverless go-to para observabilidade, registro, idempotência, validação de entrada e muito mais.

Usaremos o utilitário manipulador de eventos do Powertools.

O utilitário manipulador de eventos fornece roteamento leve para reduzir boilerplate para API Gateway REST/HTTP API, ALB e URLs de função Lambda. Ele funciona com micro funções (uma ou algumas rotas) e funções monolíticas (todas as rotas). O mais interessante é que ele tem suporte para OpenAPI e validação de dados para solicitações/respostas com esquemas Pydantic.

A documentação OpenAPI é um recurso relativamente novo. Ela fornece um endpoint '/swagger' no seu API Gateway que gera uma documentação OpenAPI.


Vamos implementar o manipulador de eventos e a validação de dados em um serviço real.

Usaremos meu projeto de modelo de livro de receitas do AWS Lambda e adicionaremos suporte para documentação OpenAPI. O Cookbook é um projeto de modelo que permite que você comece com serverless com três cliques, e ele tem todas as melhores práticas e utilitários que um serviço serverless de nível de produção requer.

Vamos começar com a configuração da infraestrutura.

 

Infraestrutura de endpoint OpenAPI

Os documentos oficiais têm exemplos de código SAM, mas eu uso o AWS CDK.

Abaixo está uma função para adicionar à sua construção de API REST do CDK.

Por design, você deve selecionar um manipulador Lambda para responder às chamadas HTTP GET '/swagger' e gerar a documentação OpenAPI. Precisamos conectar a função Lambda que usa o utilitário manipulador de eventos.

Você precisa mapear três endpoints 'GET' (/swagger, /swagger.css, /swagger.js) para essa função para a geração do swagger.

Na linha 5, a função recebe o objeto de gateway da API REST para adicionar os novos endpoints e a classe de função Lambda que atenderá esses endpoints.

Nas linhas 7 a 14, adicionamos todos os três pontos de extremidade e anexamos a função Lambda a eles com um comando HTTP GET.

Você pode encontrar o código completo aqui .

 

Código do manipulador de eventos

Agora que temos a infraestrutura toda configurada, vamos adicionar o código do manipulador de eventos e começar a documentar nossa API.


Na linha 3, criamos o resolvedor de gateway da API do manipulador de eventos e habilitamos a validação para obter os eventos de entrada e validações de resposta de saída (usando o Pydantic ).

Na linha 4, habilitamos a geração do OpenApi via endpoint '/swagger' e passamos um título para o documento gerado. De acordo com a documentação , você deve habilitar a validação para obter a definição completa do OpenAPI.


Você pode encontrar o código completo aqui .

 

Código do manipulador Lambda

Vamos escrever o código do manipulador Lambda e documentá-lo.

Documentaremos o ponto de extremidade HTTP POST '/api/orders', que cria um novo pedido do cliente.

Muita coisa está acontecendo aqui, mas é bem simples. Vamos adicionar informações OpenAPI o máximo possível. Descreveremos a API específica, sua descrição, esquemas de entrada para o payload do corpo HTTP JSON e todos os esquemas de respostas HTTP possíveis com Pydantic.


Na linha 8, importamos o manipulador de eventos que inicializamos no arquivo anterior.

Na linha 13, iniciamos a definição do aplicativo. Primeiro, marcamos essa API como um HTTP POST.

Na linha 14, definimos a API para responder ao caminho '/API/orders/.'

Na linha 15, definimos a descrição da API que aparecerá na documentação do OpenAPI.

Nas linhas 18 a 31, definimos todas as respostas da API.


Nas linhas 19-22, definimos a resposta HTTP 200 OK. É assim que podemos controlar todas as definições de resposta HTTP. Esteja ciente de que se você não definir essas respostas, o manipulador de eventos as gerará automaticamente para você e ainda incluirá as respostas 422 e 200, mas não a 501. A 422 é uma resposta interna do recurso de validação de entrada. A resposta 200 é construída usando os tipos de valor de retorno do manipulador que definimos na linha 35 - o esquema Pydantic ' CreateOrderOutput '.


Nas linhas 23-26, definimos a resposta de validação de entrada HTTP com um código HTTP 422. Usamos o esquema Pydantic ' InvalidApiRequest ' para descrevê-lo.


Nas linhas 27 a 30, fazemos o mesmo para HTTP 501.


Na linha 32, marcamos esta API como parte de um grupo chamado 'CRUD'. Quando você tem várias APIs, as tags facilitam a apresentação das APIs em várias sublistas do que em uma lista longa.


Na linha 39, definimos a função de entrada para o manipulador. O resolver chamará a subfunção correta do manipulador de eventos de acordo com o caminho HTTP e o comando. Leia mais sobre isso aqui . No nosso caso, todas as chamadas serão roteadas para a função que definimos nas linhas 13-36.


Nas linhas 34-35, usamos type hint para definir a entrada que o manipulador espera. Como habilitamos a validação de dados, assim que entramos na linha 36, temos um objeto Pydantic analisado e serializado em nossas mãos e não o evento regular como um dicionário. Usei as classes especiais Annotated e body typing para informar ao manipulador de eventos que ele espera a classe ' CreateOrderInput ' no payload do corpo e que é um dicionário JSON e não uma string.


Observe que todas as solicitações e respostas da API têm um esquema Pydantic que as define. Você pode encontrar todas as definições de esquemas Pydantic aqui e aqui .


Você pode encontrar o código completo do manipulador aqui .

Eu escrevi esse manipulador e a lógica de acordo com meus conceitos de camadas arquitetônicas, que também discuti na minha sessão AWS re:invent 2023. Clique aqui para saber mais.

 

OpenAPI Endpoint em ação

Agora, tudo o que resta é implantar nosso código e acessar nosso endpoint do Swagger.

Ficará mais ou menos assim:

Saída do OpenAPI
Saída do OpenAPI

Observe que podemos clicar nos esquemas e ver a saída da definição do Pydantic como um esquema OpenAPI adequado, com as descrições, restrições e tipos.


Você também pode conferir uma versão ao vivo do swagger aqui:

 

Limitações

Fiquei bastante impressionado com esse novo utilitário. No entanto, ele tem algumas limitações.

É solucionável, mas requer desenvolvimento da equipe do Powertools ou da comunidade.

Por exemplo, nem todas as especificações OpenAPI são geradas. No entanto, há problemas abertos no repositório, e a ajuda da comunidade é solicitada, então pode ser uma primeira contribuição significativa se você quiser tentar!


Agora, para a questão mais significativa.

No momento em que escrevo, não há suporte para geração de OpenAPI se você usar múltiplas micro funções; somente mono lambda é suportado. Criei um problema no GitHub com uma solução sugerida e apreciaria um polegar para cima no problema para dar início ao processo.

 

Resumo

Neste post, vimos como o Powertools for AWS pode ajudar você a gerar documentação OpenAPI a partir do seu código handler. Ele capacita os desenvolvedores a serem donos do código e de sua documentação e, mais importante, como mantê-los em sincronia constante.

Junte-se a mim no próximo post, onde discutirei como você pode levar essa abordagem ainda mais longe e adicionar portas importantes ao seu pipeline de CI/CD para proteger essa sincronização preciosa entre código e documentação de API.

Commenti


bottom of page