A (human) index that likes to code
Also drinks way too much coffee
Published Mar 31, 2019 12:00
While working on a hackathon project, I had difficulty getting AWS Lambda to communicate with API Gateway’s (relatively) new WebSocket Connection URL (which has the form of: https://<api gateway id>.execute-api.<region>.amazonaws.com/<stage>/@connections
),
At the time of writing, AWS Lambda provides the following environments that I use:
ApiGatewayManagementApi
:
ApiGatewayManagementApi
. Maybe it is only available on an offline installation of Boto3, but I didn’t have , so I couldn’t test it out.On the StackOverflow post that (3) and (4) came from, there was one very underrated solution by b.b3rn4rd
:
import boto3
import botocore.credentials
from botocore.awsrequest import AWSRequest
from botocore.endpoint import BotocoreHTTPSession
from botocore.auth import SigV4Auth
params = '{"name": "hello"}'
headers = {
'Host': 'ram.ap-southeast-2.amazonaws.com',
}
request = AWSRequest(method="POST", url="https://ram.ap-southeast-2.amazonaws.com/createresourceshare", data=params, headers=headers)
SigV4Auth(boto3.Session().get_credentials(), "ram", "ap-southeast-2").add_auth(request)
session = BotocoreHTTPSession()
r = session.send(request.prepare())
Credit: b.b3rn4rd
from StackOverflow
The problem with the above code is that BotocoreHTTPSession
no longer exists in newer versions of Botocore (and by extension, Boto3), and so I dived into the source code of Boto3 and botocore to find a drop-in replacement: URLLib3Session
,
Changing the code to work with API Gateway’s WebSockets Connection URL, this is what I’ve got:
import boto3
from botocore.awsrequest import AWSRequest
from botocore.httpsession import URLLib3Session
from botocore.auth import SigV4Auth
session = URLLib3Session()
data = # insert your data here
request = AWSRequest(method="POST", url="https://<api gateway id>.execute-api.<region>.amazonaws.com/<stage>/@connections/<connection id>", headers={'Host': '<api gateway id>.execute-api.<region>.amazonaws.com'}, data=json.dumps(data))
SigV4Auth(boto3.Session().get_credentials(), "execute-api", <region>).add_auth(request)
session.send(request.prepare())
With that, AWS Lambda can now interface with the AWS API Gateway WebSockets Connection URL, and can contact clients connected to the API Gateway via WebSockets. This allowed me to create a real-time dashboard that displays data from AWS DynamoDB streams, which are updated according to create/update/delete events happening to a DynamoDB table.
Well then, time use this knowledge to build the real-time app of your dreams!
Happy Coding,
CodingIndex