DEV Community

Cover image for WebSockets con Api Gateway
Javi Mora for AWS Español

Posted on

WebSockets con Api Gateway

¿Alguna vez has querido que tu app hable con tus usuarios en tiempo real, como por arte de magia? Pues bien, ¡hoy es tu día de suerte! En este post vamos a meternos de lleno en cómo darle súper poderes a tus proyectos usando WebSockets con AWS. Vamos a usar dos herramientas muy conocidas dentro del Cloud de AWS: API Gateway y Lambda. Te voy a llevar paso a paso para que crees tu propio websocket en menos de 10 minutos.

Crear el proyecto con cdk

Vamos a crear el proyecto con cdk y vamos a implementarlo con python, para ello vamos a crear nuestro directorio del proyecto y crearemos el proyecto con cdk

mkdir websocket-poc
cd websocket-poc
cdk init app --language python
Enter fullscreen mode Exit fullscreen mode

Ahora activamos el entorno virtual

source .venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Y por último instalamos las dependencias necesarias:

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Este sería el contenido de nuestro requirements.txt

aws-cdk-lib==2.114.1
constructs>=10.0.0,<11.0.0
Enter fullscreen mode Exit fullscreen mode

Creación de lambda

Usaremos una lambda para enviar un mensaje a través de nuestro websocket, para ello en nuestro proyecto cdk, y dentro de nuestro stack creamos la lambda con el siguiente código:

lambda_function = lambda_.Function(
            self, 'WebSocketHandler',
            runtime=lambda_.Runtime.PYTHON_3_8,
            handler='ws_function.handler',
            code=lambda_.Code.from_asset('./lambda'),
            timeout=core.Duration.seconds(10)
        )

lambda_function.add_to_role_policy(iam.PolicyStatement(
            actions=["execute-api:ManageConnections"],
            resources=["arn:aws:execute-api:REGION:ACCOUNT-ID:API-ID/STAGE-NAME/*"],
            effect=iam.Effect.ALLOW
        ))
Enter fullscreen mode Exit fullscreen mode

execute-api:ManageConnections permite a funciones autorizadas gestionar conexiones de clientes en API Gateway WebSockets.

Y este sería el código de la lambda, bastante sencillo, simplemente recibimos los parámetros de conexión y la url del websocket, esto podría ser fijo, pero en caso que tengamos mas de un websocket podríamos re-utilzar el código de la lambda, y por último, enviamos el mensaje "Hello, WebSocket!"

import boto3

def handler(event, context):
    connection_id = event['requestContext']['connectionId']
    gatewayapi = boto3.client("apigatewaymanagementapi",
                              endpoint_url = "https://" + event["requestContext"]["domainName"] + "/" + event["requestContext"]["stage"])

    post_data = "Hello, WebSocket!"

    gatewayapi.post_to_connection(ConnectionId=connection_id, Data=post_data.encode('utf-8'))

    return {
        'statusCode': 200,
        'body': 'Message sent'
    }

Enter fullscreen mode Exit fullscreen mode

Creación de la API

Ahora vamos a crear nuestra API que permitirá el envío de mensajes por websocket.

api = apigw.WebSocketApi(self, "WebsocketApi")
Enter fullscreen mode Exit fullscreen mode

Luego creamos un stage dentro de nuestra api:

stage = apigw.WebSocketStage(
            self, 'DevStage',
            web_socket_api=api,
            stage_name='dev',
            auto_deploy=True
        )
Enter fullscreen mode Exit fullscreen mode

Y por último añadimos una ruta específica (sendMessage" al websocket de la api y lo vinculamos a la función lambda que hemos creado previamente.

api.add_route("sendMessage",
  integration=WebSocketLambdaIntegration("SendMessageIntegration", lambda_function)
)
Enter fullscreen mode Exit fullscreen mode

Outputs

Necesitamos conocer la url de nuestro websocket para poder establecer una comunicación con el, por lo que hacemos que nos la muestre en el terminal cuando complete el despliegue de la api

core.CfnOutput(self, "WebSocketURL", value=stage.url)
Enter fullscreen mode Exit fullscreen mode

WebScocket client

Ahora vamos a usar una herramienta para simular nuestro cliente de websocket, podríamos crear una web o una app para probarlo, pero esta herramienta nos permite probar nuestro websocket mucho mas rápido y de una forma mas sencilla.

La herramienta es websocketking (https://websocketking.com/) y es muy fácil de usar.

Lo primero que debemos hacer es añadir la url de nuestro websocket que nos ha devuelto el deploy de nuestro proyecto cdk. En nuestro caso sería wss://kiyi70kcll.execute-api.eu-west-1.amazonaws.com/dev
y le damos a conectar

Conectar websocket

una vez conectados enviaremos un mensaje (puede estar vacio),simplemente es la forma mas sencilla de conocer nuestro connectionId que lo necesitaremos luego en el test de la lambda para poder enviar un mensaje a través del websocket.

Enviar mensaje al ws

{
  "message": "Forbidden",
  "connectionId": "WbqM9csoDoECF9w=",
  "requestId": "WbqUVE-OjoEFwjw="
}
Enter fullscreen mode Exit fullscreen mode

ahora copiamos nuestro connectionId y creamos un test en la lambda

y ahora enviaremos un mensaje a nuestro websocket con este JSON

{
    "requestContext": {
        "connectionId": "WbqM9csoDoECF9w=",
        "domainName": "kiyi70kcll.execute-api.eu-west-1.amazonaws.com",
        "stage": "dev"
    }
}

Enter fullscreen mode Exit fullscreen mode

donde tenemos:

  • connectionId: obtenido previamente

  • domainName: url de nuestro websocket

  • stage: stage de nuestra api

Lambda test

y realizamos nuestro test ....

comprobamos que nuestra lambda se ha ejecutado correctamente

Lambda response

y comprobamos nuestra aplicación cliente de websocket

WebSocket output

Como se puede comprobar en la imagen, nuestra comunicación a través de websocket a funcionado perfectamente :)

Precios

Ahora viene el dato delicado, si, muy bonito, pero cuanto me va a costar. Ya sabemos que el coste en AWS (y en el resto de Clouds) es de pago por uso, por lo que antes de implementar te aconsejo que vayas a la web de AWS para consultar los precios:

AWS Api Gateway Pricing

O bien también puedes ir a la calculadora de AWS y calcularlo en función de tus métricas

AWS Princing Calculator

Te pongo un ejemplo de costes calculados con la calculadora:

  • 800 Messages/minutes
  • 80 (kb) Average message size
  • 20 (seconds) Average connection duration)
  • 300 Average connection rate / minute

Y esto hace un total de 121,11 UDS / Mes

Cabe destacar que existe una capa gratuita los 12 primeros meses:

En el caso de las API WebSocket, la capa gratuita de API Gateway incluye un millón de mensajes (enviados o recibidos) y 750 000 minutos de conexión durante un máximo de doce meses.

Dependiendo de cada proyecto puede compensar o no pagar este tipo de soluciones frente a otras que necesiten mas desarrollo.

Github

El proyecto lo podéis encontrar en mi repositorio de Github

https://github.com/fjaviermoradiaz/aws-blog-websocket

Top comments (0)