Reputation: 491
I've configured a WebSocket API with API Gateway and am trying to get a custom domain name configured for it. It's a very simple API that sends messages between connected clients, which stores connection IDs in DynamoDB. In essence, it is similar to the example demonstrated here: https://aws.amazon.com/blogs/compute/announcing-websocket-apis-in-amazon-api-gateway/
All works fine when using the AWS-generated URL i.e. wss://.execute-api.us-west-2.amazonaws.com/. However, when I follow these instructions from AWS to set up a custom regional domain name, I am able to connect but am unable to send messages between clients.
I've checked the Cloudwatch logs for my Lambda functions and don't see any errors and have tried launching an entirely new environment using my CloudFormation template to no avail.
To be very clear, the following connection command triggers my Lambda function correctly and connects my client using the AWS-generated URL AND my own in Route 53.
wscat -c wss://<endpoint> <payload>
The following command, which sends a message to connected clients, works using the AWS-generated URL but NOT my own.
{ "message": "sendMessage", "toId": "193818", "data", "a random msg" }
Upvotes: 12
Views: 4503
Reputation: 123
When you use the AWS-generated URL i.e. wss://.execute-api.us-west-2.amazonaws.com/ you need to add the stage name after the URL i.e. wss://aws-generatedurl/prod.
But you must ignore the stage name from your custom domain. You can handle this with a simple if-else.
let endPointName;
let domainName = event.requestContext.domainName;
let stageName = event.requestContext.stage;
if (domainName=='mydomain.com') {
endPointName = domainName
}
else {
endPointName = domainName + '/' + stageName;
}
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: endPointName
});
Upvotes: 3
Reputation: 149
This might be a little late for an answer. This is because when using postToConnection, aws-sdk (AWS.ApiGatewayManagementApi) tries to resolve the endpoint only with it's internal resources (in this case AWS generated URLs). AWS SDK does not know about the external resources (in this case your custom domain). Therefore it works with the AWS generated URL and not your custom URL. If you want to handle this in code behind, then you might want to create a dictionary which maps your custom URLs to a AWS generated URLs. As an alternative, create a web-socket client (non aws-skd) and pass your custom URL. I haven't personally used the second approach of using a web-socket client but i'm confident it should work.
Upvotes: 0
Reputation: 636
We struggled with the same problem, however the api was returning an error:
botocore.errorfactory.ForbiddenException: An error occurred (ForbiddenException) when calling the PostToConnection operation: Forbidden
We ended up manually constructing the callback url for sending back responses: {api_id}.execute-api.{region}.amazonaws.com
.
You can get the api id from the request context passed to the lambda function.
python/boto3 code we use:
stage = event['requestContext']['stage']
api_id = event['requestContext']['apiId']
region = 'us-east-1'
domain = f'{api_id}.execute-api.{region}.amazonaws.com'
client = boto3.client('apigatewaymanagementapi', endpoint_url=f'https://{domain}/{stage}')
client.post_to_connection(
Data='...',
ConnectionId='...'
)
Upvotes: 8