How To Build Real Time Chat Application Using WebSockets with AWS API Gateway

ankana likhita sri priya
6 min readAug 19, 2019

--

Today I was stuck finding a solution on a very specific problem: find a way to create a real time chat application using WebSockets in APIGateway.

As you probably already know that, WebSocket is a computer communications protocol,used for the communication between the client and the server in bi-directional way. With these native WebSockets in API Gateway, you establish a single WebSocket connection to API Gateway from the device. Using these AWS services Let’s find a solution…!!!

  • Sign in to the aws console and at Services click on API Gateway.
Image 1: Go to services and select API Gateway.
  • Create an API
Image 2: Create API
  • Select Websocket Protocol and give your API name and create.

Route Selection Expression:$request.body.message

Image 3: Seelct Websocket and give your api name and create.
  • Your API is created.
Image 4: Your API is created.
  • Click on Routes your routes will be displayed.
Image 5: These are your routes in Api gateway.
  • Go to Services and select DynamoDB.
Image 6: Go to services and select DynamoDB.
  • Create a table.
Image 7: Create a table.
  • Give your table name and primary key. And then create the table.
Image 8: Give your table name,attributes and create.
  • DynamoDB table is created.
Image 9: Table is created.
  • Go to Services and select Lambda.
Image 10: Go to services and click on Lambda.
  • Create a lambda function.
Image 11: Create a function.
  • Give your Lambda function name and IAM role and create function.
Image 12: Give your lambda name and create function.
  • This lambda function code is for connecting to DynamoDB. And to store the connection id,username.
Image 13: Click on save.

Code:

import json
import boto3def lambda_handler(event, context):
print("event:::")
print(event)
connection_id=event['requestContext']['connectionId']
username=event['queryStringParameters']['username']

dynamodb = boto3.resource('dynamodb')
table1 = dynamodb.Table('table')
table1.put_item(
Item={
'connection_id': connection_id,
'username':username
# 'message':message

}
)return {
'statusCode': 200

}
  • Go to API Gateway and at click on Integration Request.
Image 14: click on Integration Request.
  • Integrate your lambda function here and save.
Image 15: Integrate your lambda function and save.
  • Click on Actions and select Deploy API.
Image 16: Deploy Api.
  • Create a Deployment stage and Deploy.
Image 17: Create new stage for deployment.
  • It generates a Websocket URL. Copy this url.
Image 18: Generates a websocket url.
  • To call through WebSockets we can use the wscat tool.Use this command “npm install -g wscat” in your command prompt.
Image 19: Install wsact
  • Use this commnad wscat -c “ your websocket url”?username=your username for being connected to websockets.
Image 20: Copy the websocket url and paste here.
  • So your username and connection_id will be stored in DynamoDB table.
Image 21: Your data is stored in the table.
  • Create another Lambda function for disconnecting the websocket connection.
Image 22: Create another lambda for websocket disconnection.

Code:

import json
import boto3def lambda_handler(event, context):
print("event:::")
print(event)
connection_id=event['requestContext']['connectionId']
dynamodb = boto3.resource('dynamodb')
table1 = dynamodb.Table('table')
response = table1.delete_item(
Key={
'connection_id': event['requestContext']['connectionId']

})return {
'statusCode': 200

}
  • Go to API Gateway and at $disconnect route click on Integration Request.
Image 23: click on Integration Request.
  • Integrate your lambda function here and save.
Image 24: Integrate your lambda function and save.
  • Click on Actions and select Deploy API.
Image 25: Deploy Api.
  • Select your Deployment stage and Deploy.
Image 26: Select stage for deployment.
  • It generates a Websocket URL. Copy this url.
Image 27: Generates a websocket url.
  • In your command prompt if you press CTRL + C your data will be deleted.Your connetion_id and username will be disconnected from DynamoDB table. Also when the websocket connection becomes idle the connection will be lost and deletes the data from the table.
Image 28: Data will be deleted from the table.
  • Go to PyCharm Editor or any other Editors and create a python file. This code is used for query on DynamoDB to get all the connection ids, and send messages to them. Get a message from the device and send the message to all the devices that are connected to the WebSocket API.
Image 29: Go to pycharm editor and enter this code.

Code:

import boto3
import ast
import hmac
import base64
import json
import uuid
from botocore.exceptions import ClientError
from boto3.dynamodb.conditions import Key, Attr
import logging
import urllib3
logger = logging.getLogger('dev')
logger.setLevel(logging.DEBUG)
client = boto3.client('apigatewaymanagementapi')dynamodb = boto3.resource('dynamodb', region_name='us-west-2')
# table = dynamodb.Table('chatp')
def _send_to_connection(connection_id, data, event):
gatewayapi = boto3.client("apigatewaymanagementapi",
endpoint_url = "https://" + event["requestContext"]["domainName"] +
"/" + event["requestContext"]["stage"])
response = gatewayapi.post_to_connection(ConnectionId=connection_id,
Data=json.dumps(data).encode('utf-8'))
print(response)
print("response>>>>>>>")
return response
def lambda_handler(event, context):
print(event)
table = dynamodb.Table("table")
response = table.scan()
data1 = response['Items']
length = data1.__len__()
print("data1:::")
print(data1)
# items = response.get("Items", [])
# connections = [x["Connectionid "] for x in items if "Connectionid " in x]
# print(connections)
# Send the message data to all connections
# playersTable = dynamodb.Table('PLAYER_DETAILS')
connectionId = event['requestContext']['connectionId']
playerDetailsObj = table.scan(
FilterExpression=Attr('connection_id').eq(connectionId)
)
playerDetails = playerDetailsObj['Items']
username = ""
print("playerDetails:::")
print(playerDetails)
for x in range(length):
if data1[x]['connection_id'] == connectionId:
username = data1[x]['username']
message1 = event['body']
message2 = ast.literal_eval(message1)
message = message2['message']
print(message)
logger.debug("Broadcasting message: {}".format(message))
data = {username: message}
valresp = ""
for
x in range(length):
connectionID = data1[x]['connection_id']
valresp = _send_to_connection(connectionID, data, event)
print(valresp)
return {'statusCode':200}
  • Install the latest versions of boto3, boto3–1.9.128.dist-info, botocore, botocore-1.12.128.dist-info, urllib3, urllib3–1.24.1.dist-info. Zip all these modules along with your python file.
Image 30: Zip the modules and python file.
  • Create another lambda for getting a message from the device and send the message to all the devices that are connected to the WebSocket API. Upload your zip file and save.
Image 31: Create another lambda function.
  • Give your custom route name and save in API Gateway.
Image 32: Create a custom route.
  • Integrate your lambda here and save.
Image 33: Integrate your lambda function and save.
  • Click on Actions and select Deploy API.
Image 34: Deploy Api.
  • Select your Deployment stage and Deploy.
Image 35: Select stage for deployment.
  • It generates a Websocket URL. Copy this url.
Image 36: Generates a websocket url.
  • Take another command prompt and install wscat “npm install -g wscat” . Use this command wscat -c “your websocket url”?username=your username for connecting to multiple devices.

Message Format:

{"action" : "onMessage" , "message" : "Hey Hi....."}
Image 37: Enter the mesage you want in given message format.
  • Two users connected to this web socket url and started their conversation. If you want you can send this web socket url to others install the wscat an enter your webscocket url. And start doing conversations with them from multiple devices.
Image 38: Connecting to multiple devices and started conversation.
Image 39: Connecting to multiple devices and started conversation.

Using this solution, we can connect to multiple devices and start conversations with multiple users using web sockets.

Ok, that’s it. I hope you found this case useful! See you next time.

--

--