Como usar Websockets com o AWS API Gateway

Olá, pessoal. Tudo bem?

No final do ano passado (2018), a AWS disponibilizou no serviço de API Gateway, a possibilidade de utilizarmos Websockets. A ideia neste post é apresentarmos alguns conceitos desta tecnologia bem bacana.

Porque usar o API Gateway e Websockets?

Apesar de existirem diversas tecnologias que gerenciam todo o ciclo de vida de websockets, alguns problemas, principalmente relacionados a infraestrutura (como disponibilidade e otimização de recursos), são mais complexos de serem abordados.

O API Gateway, por ser serverless, elimina basicamente toda a preocupação que teríamos com a infraestrutura, e oferece uma forma simples e prática de interação entre cliente e servidor. Além de evitar qualquer ociosidade de hardware, o que implica em redução de custos.

Como funciona?

Diferentemente do API Gateway usando REST, a versão com Websockets introduz um novo conceito chamado route (rota), que tem a responsabilidade de identificar como aquela mensagem será tratada.

Existem três rotas padrões, que são extremamente importantes:

  • $connect: Se houver uma nova conexão, está rota será utilizada. Neste processo é gerado um ConnectionId, que deve ser armazenado para podermos identificar o cliente do lado do servidor (geralmente para enviar respostas ou gerir a conexão);
  • $disconnect: Sempre que a API identificar que uma conexão foi encerrada, está rota será executada;
  • $default: Quando não for possível identificar a rota em uma mensagem, ela será encaminhada para a rota padrão (default).

Para ter uma ideia melhor de como tudo funciona, vamos criar uma Web API.

Criando a WebAPI

Quando uma nova API é criada usando websockets, veremos um campo chamado Route Selection Expression. Neste campo devemos informar a expressão que irá identificar o que será o identificador da rota, dentro das mensagens recebidas.

Criação de uma webapi utilizando WebSockets

Como exemplo, poderíamos utilizar o valor $request.body.route no Route Selection Expression. Uma mensagem com o body abaixo estaria no padrão para ser roteada por esta API.

{
  "route": "myRoute",
  "message": {
    "id": 123,
    "content": "anything"
  }
}

Isso fará com que esta mensagem seja encaminhada para a rota myRoute. No diagrama abaixo, temos uma exemplo de como as rotas são endereçadas.

Api Gateway com websockets

Ok, mas como definimos uma rota?

Boa pergunta. É bem simples.

Depois de criarmos a api, devemos selecionar o menu Routes, digitar o nome da rota (onde diz New Route Key) e confirmar.

Feito isto, teremos a rota criada e algumas opções de integração. Para este exemplo, iremos selecionar Lambda Function.

Criação de uma rota

Não entrarei nos detalhes da criação da Lambda neste post, mas é possível encontrar uma excelente documentação aqui.

Algumas informações importantes que deveremos considerar ao criar uma rota integrando a AWS Lambda:

  • Use Lambda Proxy Integration: Identifica se a mensagem será encaminhada na íntegra à Lambda. Caso não seja utilizado, podemos definir um template de transformação da mensagem, para simplificar e tornar o modelo mais coeso. Idêntico ao disponível no API Gateway com REST;
  • Lambda Region: A region onde está a Lambda que será invocada por esta rota;
  • Lambda Function: Identifica a Lambda Function;
  • Invoke with caller credentials: Se marcado, usará credenciais recebidas na request;
  • Execution Role: Permite informar o ARN de uma role para invocar a função Lambda;
  • Use default timeout: Indica se será usado o timeout padrão de 29 segundos;
  • Custom Timeout: Caso não seja usado o valor padrão, permite informar um valor customizado para o timeout.

Como enviar uma resposta do servidor para o cliente?

Quando a Lambda (ou outro serviço) precisar encaminhar uma resposta para algum dos clientes, é possível enviar um HTTP POST para o endpoint @connections do API Gateway. O @connections, permite interagirmos com os clientes conectados, usando métodos HTTP:

  • GET: Obtém o status da conexão;
  • POST: Envia uma mensagem para um cliente;
  • DELETE: Desconecta um cliente.

Como exemplo podemos enviar a mensagem “Hello WebSockets!” para o endereço abaixo:

https://myapi.execute-api.us-east-1.amazonaws.com/stage/@connections/connectionId

Reforçando o que foi dito sobre o ID da conexão (connectionId) no início deste post, é necessário armazená-lo para usarmos nestas situações. 🙂

Para ilustrar um pouco melhor como funciona essa resposta, abaixo segue mais um diagrama.

Websocket – @connections

Importante: Para utilizar o @connections, precisamos autorizar as requisições através do Signature Version 4.

Por hoje era isso, pessoal! Já utilizou websockets com o API Gateway? Deixe sua experiência nos comentários!

Abraços, e até a próxima.

Postado em AWS

Deixe uma resposta