Uma API ruby com AWS Lambda e Serverless Framework

mtayllan

Tayllan

Posted on April 19, 2020

Uma API ruby com AWS Lambda e Serverless Framework

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'
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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.

  1. Acesse sua conta da AWS e então acesse Serviços > IAM > Usuários > Adicionar Usuário.
  2. Dê um nome. Eu coloquei serverless-test.
  3. Habilite acesso programático e vá para a aba anexar políticas existentes de forma direta.
  4. Selecione AdministratorAccess e finalize a criação do usuário.
  5. Acesse a página do usuário que você criou, vá em credenciais de segurança.
  6. 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 
Enter fullscreen mode Exit fullscreen mode

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 (em package).

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.

  1. Execute bundle install --standalone --path vendor/bundle
  2. 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

Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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 significa entidade 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 
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
mtayllan
Tayllan

Posted on April 19, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related