Uma API ruby com AWS Lambda e Serverless Framework
Tayllan
Posted on April 19, 2020
O AWS Lambda nos permite que com alguns poucos passos possamos ter uma aplicação no ar, sem ter que configurar ou gerenciar servidores. Além disso, você só paga por tempo de computação, então podemos entregar pequenos serviços com velocidade e baixo custo.
Os principais casos de uso do AWS Lambda são: Processamento de arquivos e streams em tempo real e backend de aplicações web, iot ou mobile.
Quero mostrar como podemos criar uma pequena API em ruby e disponibilizá-la para consumo em poucos minutos e com todo um ambiente robusto e autoescalável para realização de suas tarefas.
O que é o Serverless Framework?
É uma ferramenta Open Source que te ajuda a fazer deploy e configuração de aplicações serverless em várias plataformar diferentes (AWS, GCloud, Azure, etc). Com um simples arquivo de configuração .yml
podemos descrever tudo que nossa aplicação precisa.
Vamos ao código!
Iremos desenvolver uma aplicação que você passa como entrada um CEP qualquer e a API retornará o endereço completo.
Aqui utilizarei Ruby 2.7.0 e minha conta da AWS. Dado o nosso uso, nada será cobrado, pois o Lambda tem um nível de uso gratuito.
O nível de uso gratuito do AWS Lambda inclui 1 milhão de solicitações gratuitas por mês e 400.000 GB/segundos de tempo de computação por mês.
Instalando o Serverless Framework
Recomendo que você tenha Node 6 ou maior instalado e o npm
, pois facilita a instalação de alguns plugins que o serverless nos fornece.
Feito isso, basta executar o comando npm install -g serverless
e estamos prontos.
Criando o projeto
Crie um repositório lambda-ruby-api
e então execute bundle init
.
Para o nosso projeto, vamos precisar da gem correios-cep, então adicione ela ao Gemfile
e execute bundle install
# frozen_string_literal: true
source 'https://rubygems.org'
gem 'correios-cep'
Agora vamos criar nossa função em um arquivo chamado handler.rb
# frozen_string_literal: true
require 'correios-cep'
def handler(event:, context:)
cep = event['pathParameters']['cep']
address = Correios::CEP::AddressFinder.get(cep)
{ statusCode: 200, body: JSON.generate(address) }
end
Nossa função recebe o event
, que é um JSON que conterá os dados de entrada para o processamento de nossa função. O context
contem informações sobre o nome da função, versão, arn, limite de memória, etc. Não utilizaremos o context
nessa aplicação.
No corpo do event
, iremos receber o cep
e então chamaremos o AddressFinder
da gem para buscar o endereço que precisamos.
Por fim, retornamos um statusCode 200 para indicar que tudo deu certo e o endereço que foi processado pela gem, em JSON.
Observações!!
Nosso endpoint da api será da forma https://.../cep_aqui
Para acessar isso via lambda, usamos o pathParameters. A nossa key serácep
.
Isso será definido nos próximos passos.
Configurando Serverless Framework
Agora precisamos fazer algumas configurações para fazer o deploy da nossa aplicação.
Para que o Serverless possa fazer uso da AWS precisamos criar algumas credenciais para ele usar.
- Acesse sua conta da AWS e então acesse Serviços > IAM > Usuários > Adicionar Usuário.
- Dê um nome. Eu coloquei serverless-test.
- Habilite acesso programático e vá para a aba anexar políticas existentes de forma direta.
- Selecione
AdministratorAccess
e finalize a criação do usuário. - Acesse a página do usuário que você criou, vá em credenciais de segurança.
- Clique em criar chave de acesso e guarde essas chaves.
Voltando agora para nosso terminal, basta digitar o seguinte comando para dar permissão de acesso a AWS ao serverless.
serverless config credentials --provider aws --key=key_id --secret=key_secret
Substitua o key_id
pela sua chave e key_secret
por sua chave secreta.
⚠️ Atenção!
Aqui estamos habilitando acesso máximo a AWS, já que estamos apenas testando isso agiliza nosso processo de entendimento. Entretanto, recomendo que depois você configure um acesso mais específico para o serverless. Veja mais aqui.
serverless.yml
Para que o deploy seja feito, devemos criar um arquivo .yml que define os requisitos da nossa aplicação. O nosso arquivo será o seguinte:
service: ruby-cep # nome da nossa função lambda
provider:
name: aws # onde vamos fazer o deploy
runtime: ruby2.7 # linguagem que vamos utilizar
plugins:
- serverless-ruby-package # plugin para empacotamento de dependencias
package: # o que queremos que seja enviado para o AWS Lambda
include: # tudo que precisamos para que função funcione
- handler.rb
- vendor/**
functions: # podemos definir várias funções em uma configuração só
api: # vamos definir apenas nosso endpoint api para ceps
handler: handler.handler # onde está nossa função
events: # eventos no qual ela será disparada
- http: # chamando via http
path: /{cep} # caminho e o parâmetro cep
method: get
cors: true # habilita chamada de todas as origens
Sobre o serverless-ruby-package
Precisamos que nossas dependencias sejam enviadas para o Lmabda também, a fim de que possam ser utilizadas. Esse plugin nos ajuda com esse processo removendo todos os arquivos e nos forçando a definir quais queremos que sejam enviados (empackage
).Para instalar o plugin basta executar
npm i serverless-ruby-package --save
Fazendo o deploy
Temos que fazer uma pequena alteração para que possamos carregar as dependencias da nossa função.
- Execute
bundle install --standalone --path vendor/bundle
- Modifique
handler.rb
# frozen_string_literal: true
load 'vendor/bundle/bundler/setup.rb' # adicionado
require 'correios-cep'
def handler(event:)
cep = event['pathParameters']['cep']
address = Correios::CEP::AddressFinder.get(cep)
{ statusCode: 200, body: JSON.generate(address) }
end
Agora é só ir no terminal e executar serverless deploy
, aguarde alguns minutos e pronto! Você terá um output similar a este.
Serverless: Stack update finished...
Service Information
service: ruby-cep
stage: dev
region: us-east-1
stack: ruby-cep-dev
resources: 11
api keys:
None
endpoints:
GET - https://some-id.execute-api.us-east-1.amazonaws.com/dev/
functions:
api: ruby-cep-dev-api
layers:
None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.
Veja que ele já nos deu o endpoint que configuramos! Vamos lá testar se funciona 😄
Copie e cole no seu navegador o caminho com seu CEP para testar.
Exemplo: https://some-id.execute-api.us-east-1.amazonaws.com/dev/00000-000
E aí? Deu certo ⁉️
Atualizando a função
Agora queremos adicionar mais funcionalidades, como retornar diferentes respostas quando recebermos um CEP inválido.
O CEP pode ser inválido tanto por estar escrito em um formato inválido (Ex: 00-0) ou por não existir. Fazemos algumas modificações:
# frozen_string_literal: true
load 'vendor/bundle/bundler/setup.rb'
require 'correios-cep'
def handler(event:, context:)
cep = event['pathParameters']['cep']
address = Correios::CEP::AddressFinder.get(cep)
if address.empty?
{ statusCode: 404 }
else
{ statusCode: 200, body: JSON.generate(address) }
end
rescue ArgumentError
{ statusCode: 422 }
end
A gem dos correios faz uma validação no formato do cep, se for inválido ele dispara uma exceção do tipo ArgumentError
e nós a capturamos. 😄
404 significa
não encontrado
422 significaentidade não processável
Para fazer o deploy rápido dessas modificações basta rodar o comando:
serverless deploy function -f api
Nesse caso api
é o nome da função que declaramos dentro da chave functions
do nosso serverless.yml
# ...
functions:
api: # aqui
handler: handler.handler
events:
- http:
path: /{cep}
method: get
cors: true
Rapidamente a função será atualizada e agora podemos verificar se está tudo ok. Teste um cep inválido e veja as mensagens retornadas.
Exemplos inválidos:
404:https://some-id.execute-api.us-east-1.amazonaws.com/dev/00000-000
422:https://some-id.execute-api.us-east-1.amazonaws.com/dev/0
Conclusão
Com AWS Lambda e Serverless Framework podemos construir e entregar pequenas e úteis aplicações rapidamente. O que mostrei aqui foi só um pequeno exemplo, mas podemos criar aplicações bem grandes para executar nessa infraestrutura e economizar alguns gastos.
Código fonte: https://github.com/mtayllan/lambda-ruby-api
Posted on April 19, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.