How to send a response back to client using websockets in AWS Lambda

Viewed 2192

I am using the Serverless Framework to deploy a WebSocket app to AWS Lambda.

I need to make it send a response back to the client when it hits a WebSocket route.

Here is my handler:

const AWS = require("aws-sdk");

module.exports.websocketHandler = async (event, _) => {
  const {
    requestContext: { routeKey }
  } = event;

  switch (routeKey) {
    case "$connect":
      // ....
      break;

    case "$disconnect":
      // ....
      break;

    case "getBot":
      const body = JSON.parse(event.body);
      const postData = body.data;
      const params = {
        ConnectionId: event.requestContext.connectionId,
        Data: JSON.stringify(postData)
      };

      postMessage(params, event);
      break;

    case "$default":
    default:
      return { statusCode: 200 };
  }

  return { statusCode: 200 };
};

const postMessage = async (data, event) => {
  try {
    const apigwManagementApi = new AWS.ApiGatewayManagementApi({
      apiVersion: "2018-11-29",
      `https://${event.requestContext.domainName}/${event.requestContext.stage}`
    });

    await apigwManagementApi.postToConnection(data).promise();
  } catch (err) {
    console.log(err);
  }
};

It just responds back with whatever was sent. I am using wscat tool to connect to the WebSocket.

wscat -c wss://{API-ID}.execute-api.{REGION}.amazonaws.com/dev
{"action": "getBot", "data": "Hello world"}

I have tried testing it offline, and it works just fine. And when deployed, I can connect to it, but whenever I try to send the action to getBot, I get no response.

2 Answers

The problem was with my lambda, It was in a custom VPC which resulted in lambda not getting internet access.

I fixed this by adding additional subnets with a NAT Gateway in AWS.

For others coming to this question, you need to do a few things:

  1. Create a WebSocket API with the API Gateway.
  2. Create route keys for each WS event you need to handle.
  3. Simultaneously while creating route keys (or before), create Lambda functions for each WS event. Connect your given Lambda function to the WS API route. (Be sure to deploy your Lambda functions)
  4. Ensure your permissions are setup correctly for each Lambda function (make sure the API Gateway can access them).
  5. Deploy your WS API from the API Gateway. Use the wss://[...] URL to connect via a client.

Helpful docs: https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-develop.html

Enjoy!

Related