in Blueprints/BlueprintDefinitions/vs2022/WebSocketAPIServerless/template/src/BlueprintBaseName.1/Functions.cs [115:214]
public async Task<APIGatewayProxyResponse> SendMessageHandler(APIGatewayProxyRequest request, ILambdaContext context)
{
try
{
// Construct the API Gateway endpoint that incoming message will be broadcasted to.
var domainName = request.RequestContext.DomainName;
var stage = request.RequestContext.Stage;
var endpoint = $"https://{domainName}/{stage}";
context.Logger.LogInformation($"API Gateway management endpoint: {endpoint}");
// The body will look something like this: {"message":"sendmessage", "data":"What are you doing?"}
JsonDocument message = JsonDocument.Parse(request.Body);
// Grab the data from the JSON body which is the message to broadcasted.
JsonElement dataProperty;
if (!message.RootElement.TryGetProperty("data", out dataProperty) || dataProperty.GetString() == null)
{
context.Logger.LogInformation("Failed to find data element in JSON document");
return new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.BadRequest
};
}
var data = dataProperty.GetString() ?? "";
var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data));
// List all of the current connections. In a more advanced use case the table could be used to grab a group of connection ids for a chat group.
var scanRequest = new ScanRequest
{
TableName = ConnectionMappingTable,
ProjectionExpression = ConnectionIdField
};
var scanResponse = await DDBClient.ScanAsync(scanRequest);
// Construct the IAmazonApiGatewayManagementApi which will be used to send the message to.
var apiClient = ApiGatewayManagementApiClientFactory(endpoint);
// Loop through all of the connections and broadcast the message out to the connections.
var count = 0;
foreach (var item in scanResponse.Items)
{
var postConnectionRequest = new PostToConnectionRequest
{
ConnectionId = item[ConnectionIdField].S,
Data = stream
};
try
{
context.Logger.LogInformation($"Post to connection {count}: {postConnectionRequest.ConnectionId}");
stream.Position = 0;
await apiClient.PostToConnectionAsync(postConnectionRequest);
count++;
}
catch (AmazonServiceException e)
{
// API Gateway returns a status of 410 GONE then the connection is no
// longer available. If this happens, delete the identifier
// from our DynamoDB table.
if (e.StatusCode == HttpStatusCode.Gone)
{
var ddbDeleteRequest = new DeleteItemRequest
{
TableName = ConnectionMappingTable,
Key = new Dictionary<string, AttributeValue>
{
{ConnectionIdField, new AttributeValue {S = postConnectionRequest.ConnectionId}}
}
};
context.Logger.LogInformation($"Deleting gone connection: {postConnectionRequest.ConnectionId}");
await DDBClient.DeleteItemAsync(ddbDeleteRequest);
}
else
{
context.Logger.LogInformation($"Error posting message to {postConnectionRequest.ConnectionId}: {e.Message}");
context.Logger.LogInformation(e.StackTrace);
}
}
}
return new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK,
Body = "Data sent to " + count + " connection" + (count == 1 ? "" : "s")
};
}
catch (Exception e)
{
context.Logger.LogInformation("Error disconnecting: " + e.Message);
context.Logger.LogInformation(e.StackTrace);
return new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.InternalServerError,
Body = $"Failed to send message: {e.Message}"
};
}
}