Websocket with API Gateway AWS | Websocket con API Gateway AWS

Ejemplo de implementación de Websocket con API Gateway de AWS.

Cloudformation:

  
      
        AWSTemplateFormatVersion: '2010-09-09'
        #Transform: AWS::Serverless-2016-10-31
        Description: websockets to notify to the frontend. 

        Parameters:
          WebSocketName:
            Description: Websocket name
            Type: String

        Resources:

          WebSocket:
            Type: AWS::ApiGatewayV2::Api
            Properties:
              Name: !Sub ${WebSocketName}
              ProtocolType: WEBSOCKET
              RouteSelectionExpression: "$request.body.action"
              Description: "Mock WebSocket API Gateway."

          ConnectRoute:
            Type: AWS::ApiGatewayV2::Route
            Properties:
              ApiId: !Ref WebSocket
              RouteKey: $connect
              #RouteResponseSelectionExpression: '$default'
              AuthorizationType: NONE
              OperationName: ConnectRoute
              Target: !Join
                - '/'
                - - 'integrations'
                  - !Ref ConnectInteg

          ConnectInteg:
            Type: AWS::ApiGatewayV2::Integration
            Properties:
              ApiId: !Ref WebSocket
              Description: Connect Integration
              IntegrationType: AWS_PROXY
              IntegrationUri: 
                Fn::Sub:
                    arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:register-conection-websocket-http/invocations

          DisconnectRoute:
            Type: AWS::ApiGatewayV2::Route
            Properties:
              ApiId: !Ref WebSocket
              RouteKey: $disconnect
              AuthorizationType: NONE
              OperationName: DisconnectRoute
              Target: !Join
                - '/'
                - - 'integrations'
                  - !Ref DisconnectInteg

          DisconnectInteg:
            Type: AWS::ApiGatewayV2::Integration
            Properties:
              ApiId: !Ref WebSocket
              Description: Disconnect Integration
              IntegrationType: AWS_PROXY
              IntegrationUri: 
                Fn::Sub:
                    arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:register-conection-websocket-http/invocations

          DefaultRoute:
            Type: AWS::ApiGatewayV2::Route
            Properties:
              ApiId: !Ref WebSocket
              RouteKey: $default
              AuthorizationType: NONE
              OperationName: DefaultRoute
              Target: !Join
                - '/'
                - - 'integrations'
                  - !Ref DefaultInteg

          DefaultInteg:
            Type: AWS::ApiGatewayV2::Integration
            Properties:
              ApiId: !Ref WebSocket
              Description: Default Integration
              IntegrationType: AWS_PROXY
              IntegrationUri: 
                Fn::Sub:
                    arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:default-websocket-http/invocations

          GetConnectionRoute:
            Type: AWS::ApiGatewayV2::Route
            Properties:
              ApiId: !Ref WebSocket
              RouteKey: getConnectionId
              AuthorizationType: NONE
              OperationName: GetConnectionRoute
              Target: !Join
                - '/'
                - - 'integrations'
                  - !Ref GetConnectionInteg

          GetConnectionInteg:
            Type: AWS::ApiGatewayV2::Integration
            Properties:
              ApiId: !Ref WebSocket
              Description: Get Connection Integration
              IntegrationType: AWS_PROXY
              IntegrationUri: 
                Fn::Sub:
                    arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:get-connection-websocket-http/invocations

          Deployment:
            Type: AWS::ApiGatewayV2::Deployment
            DependsOn:
            - ConnectRoute
            - DefaultRoute
            - DisconnectRoute
            - GetConnectionRoute
            Properties:
              ApiId: !Ref WebSocket

          Stage:
            Type: AWS::ApiGatewayV2::Stage
            Properties:
              StageName: default
              Description: None
              DeploymentId: !Ref Deployment
              ApiId: !Ref WebSocket
      
  

Lambdas:

  
      
          lambda name: default-websocket-http
          async function(event, context) {
              return;
          }

          lambda name: get-connection-websocket-http
          async function(event, context) {
              const connectionId = event.requestContext.connectionId;
              const domainName = event.requestContext.domainName;

               const message = JSON.stringify({
                  statusCode: 200,
                  body: {
                      code: 'CONNECTION_ID',
                      connectionId: connectionId,
                  }
              });
              const apigwManagementApi = new AWS.ApiGatewayManagementApi({ apiVersion: "2018-11-29", endpoint: domainName });
              const params = {
                  ConnectionId: connectionId,
                  Data: message,
              };
              await apigwManagementApi.postToConnection(params).promise();
          }



          lambda name: register-conection-websocket-http
          async function(event, context) {
              const connectionId = event.requestContext.connectionId;
              const domainName = event.requestContext.domainName;
              const eventType = event.requestContext.eventType;
              if (eventType === 'CONNECT') {
                  // save connection in dynamodb
                  await putConnection(input.connectionId, domainName);
              } else if (input.eventType === 'DISCONNECT') {
                  // delete connection in dynamodb
                  deleteConnection(input.connectionId);
              }
          }


          lambda name: send-notification-http
          async function(event, context) {
              const connectionId = event.requestContext.connectionId;
              const domainName = event.requestContext.domainName;
              const eventType = event.requestContext.eventType;

              //Buscar en Dynamodb
              const connections = getConnectionsToNotify();

              if (connections && connections.length > 0) {
                  for (const connection of connections) {
                      const message = JSON.stringify({
                          statusCode: 200,
                          body: {
                              code: 'CONNECTION_ID',
                              connectionId: connectionId,
                          }
                      });
                      const apigwManagementApi = new AWS.ApiGatewayManagementApi({ apiVersion: "2018-11-29", endpoint: domainName });
                      const params = {
                          ConnectionId: connectionId,
                          Data: message,
                      };
                      await apigwManagementApi.postToConnection(params).promise();
                  }
              }
          }
      
  
  	
    	const socket = new WebSocket("wss://${ID_API}.execute-api.us-east-1.amazonaws.com/default");
        
        socket.onopen = function (e) {
          console.log("[open] Connection established", e);
          socket.send(JSON.stringify({
            action: "getConnectionId"
          }))
        };
        
        socket.onmessage = function (event) {
          console.log(`[message] Data received from server: ${event.data}`);
          const data = JSON.parse(event.data);
        };
    
  

Comentarios

Entradas más populares de este blog

Ejemplo Log4j 2 en JAVA | Log4j 2 en Springboot | Configuración Log4j 2 | Log4j 2 in SpringBoot| Example Log4j 2 in SpringBoot | Configuring Log4j 2

Python: Inyección de dependencias

GOlang con Docker | GOlang with Docker | GO con Docker | GO with Docker