コード例 #1
0
        internal static Task SendMessage(string apiUrl, string connectionId, string room, JObject message)
        {
            Task result = Task.Run(() => {
                MemoryStream stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(message.ToString(Newtonsoft.Json.Formatting.None)));
                AmazonApiGatewayManagementApiConfig config = new AmazonApiGatewayManagementApiConfig()
                {
                    ServiceURL = apiUrl
                };
                AmazonApiGatewayManagementApiClient client = new AmazonApiGatewayManagementApiClient(config);
                PostToConnectionRequest postReq            = new PostToConnectionRequest()
                {
                    ConnectionId = connectionId, Data = stream
                };
                try
                {
                    Logging.LogDebug("Sending to: " + connectionId);
                    Task <PostToConnectionResponse> task = client.PostToConnectionAsync(postReq);
                    task.Wait();
                    Logging.LogDebug("Sent to: " + connectionId);
                }
                catch (Exception ex)
                {
                    Logging.LogDebug("Deleteing conneciton " + connectionId);
                    error = apiUrl + " - " + connectionId + " - " + ex.ToString();
                    Connection.Delete(apiUrl, room, connectionId);
                    Logging.LogDebug("Deleted conneciton " + connectionId);
                }
            });

            return(result);
        }
コード例 #2
0
        public APIGatewayProxyResponse Message(APIGatewayProxyRequest request)
        {
            Console.WriteLine("ConnectionId: " + request.RequestContext.ConnectionId);
            Request finalRequest = JsonConvert.DeserializeObject <Request>(request.Body);

            Asset    asset    = new Asset();
            Document document = asset.getItem(finalRequest.ContractId);
            AmazonApiGatewayManagementApiClient client = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig()
            {
                ServiceURL = "https://" + request.RequestContext.DomainName + "/" + request.RequestContext.Stage
            });

            MemoryStream            stream      = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(document)));
            PostToConnectionRequest postRequest = new PostToConnectionRequest()
            {
                ConnectionId = request.RequestContext.ConnectionId,
                Data         = stream
            };

            var result = client.PostToConnectionAsync(postRequest);

            result.Wait();

            return(new APIGatewayProxyResponse
            {
                StatusCode = (int)HttpStatusCode.OK
            });
        }
コード例 #3
0
        public async Task PostToConnection(ConnectionSocketModel connection, MemoryStream stream, ConnectionSocketService connectionService, AmazonApiGatewayManagementApiClient apiClient, ILambdaContext context)
        {
            var connectionId = connection.connection_id;

            context.Logger.LogLine($"Get Connection ID from DB: {connectionId}");

            var postConnectionRequest = new PostToConnectionRequest
            {
                ConnectionId = connectionId,
                Data         = stream
            };

            try
            {
                context.Logger.LogLine($"Post to connection: {connectionId}");
                stream.Position = 0;
                await apiClient.PostToConnectionAsync(postConnectionRequest);
            }
            catch (AmazonServiceException e)
            {
                if (e.StatusCode == HttpStatusCode.Gone)
                {
                    connectionService.GetConnection(connectionId);
                    context.Logger.LogLine($"Deleting gone connection: {connectionId}");
                }
                else
                {
                    context.Logger.LogLine($"Error posting message to {connectionId}: {e.Message}");
                    context.Logger.LogLine(e.StackTrace);
                }
            }
        }
コード例 #4
0
        public void ProcessDynamoEvent(DynamoDBEvent dynamoDBEvent, ILambdaContext context)
        {
            AmazonApiGatewayManagementApiClient client = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig()
            {
                ServiceURL = "https://g49fepw5h8.execute-api.us-west-2.amazonaws.com/Test"
            });

            AmazonDynamoDBClient amazonDynamoDbClient = new AmazonDynamoDBClient();

            Console.WriteLine("Voy a empezar");
            Console.WriteLine(dynamoDBEvent.Records);

            foreach (var dynamoRecord in dynamoDBEvent.Records)
            {
                MemoryStream stream      = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dynamoRecord.Dynamodb.NewImage)));
                String[]     connections = GetConnections(amazonDynamoDbClient, dynamoRecord.Dynamodb.NewImage);
                foreach (string connection in connections)
                {
                    PostToConnectionRequest postRequest = new PostToConnectionRequest()
                    {
                        ConnectionId = connection,
                        Data         = stream
                    };

                    var result = client.PostToConnectionAsync(postRequest);
                    result.Wait();
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Initiates the asynchronous execution of the PostToConnection operation.
        /// </summary>
        ///
        /// <param name="request">Container for the necessary parameters to execute the PostToConnection operation on AmazonApiGatewayManagementApiClient.</param>
        /// <param name="callback">An AsyncCallback delegate that is invoked when the operation completes.</param>
        /// <param name="state">A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback
        ///          procedure using the AsyncState property.</param>
        ///
        /// <returns>An IAsyncResult that can be used to poll or wait for results, or both; this value is also needed when invoking EndPostToConnection
        ///         operation.</returns>
        /// <seealso href="http://docs.aws.amazon.com/goto/WebAPI/apigatewaymanagementapi-2018-11-29/PostToConnection">REST API Reference for PostToConnection Operation</seealso>
        public virtual IAsyncResult BeginPostToConnection(PostToConnectionRequest request, AsyncCallback callback, object state)
        {
            var options = new InvokeOptions();

            options.RequestMarshaller    = PostToConnectionRequestMarshaller.Instance;
            options.ResponseUnmarshaller = PostToConnectionResponseUnmarshaller.Instance;

            return(BeginInvoke(request, options, callback, state));
        }
コード例 #6
0
        /// <summary>
        /// Sends the provided data to the specified connection.
        /// </summary>
        /// <param name="request">Container for the necessary parameters to execute the PostToConnection service method.</param>
        /// <param name="cancellationToken">
        ///     A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        ///
        /// <returns>The response from the PostToConnection service method, as returned by ApiGatewayManagementApi.</returns>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.ForbiddenException">
        /// The caller is not authorized to invoke this operation.
        /// </exception>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.GoneException">
        /// The connection with the provided id no longer exists.
        /// </exception>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.LimitExceededException">
        /// The client is sending more than the allowed number of requests per unit of time or
        /// the WebSocket client side buffer is full.
        /// </exception>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.PayloadTooLargeException">
        /// The data has exceeded the maximum size allowed.
        /// </exception>
        /// <seealso href="http://docs.aws.amazon.com/goto/WebAPI/apigatewaymanagementapi-2018-11-29/PostToConnection">REST API Reference for PostToConnection Operation</seealso>
        public virtual Task <PostToConnectionResponse> PostToConnectionAsync(PostToConnectionRequest request, System.Threading.CancellationToken cancellationToken = default(CancellationToken))
        {
            var options = new InvokeOptions();

            options.RequestMarshaller    = PostToConnectionRequestMarshaller.Instance;
            options.ResponseUnmarshaller = PostToConnectionResponseUnmarshaller.Instance;

            return(InvokeAsync <PostToConnectionResponse>(request, options, cancellationToken));
        }
コード例 #7
0
        /// <summary>
        /// Sends the provided data to the specified connection.
        /// </summary>
        /// <param name="request">Container for the necessary parameters to execute the PostToConnection service method.</param>
        ///
        /// <returns>The response from the PostToConnection service method, as returned by ApiGatewayManagementApi.</returns>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.ForbiddenException">
        /// The caller is not authorized to invoke this operation.
        /// </exception>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.GoneException">
        /// The connection with the provided id no longer exists.
        /// </exception>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.LimitExceededException">
        /// The client is sending more than the allowed number of requests per unit of time or
        /// the WebSocket client side buffer is full.
        /// </exception>
        /// <exception cref="Amazon.ApiGatewayManagementApi.Model.PayloadTooLargeException">
        /// The data has exceeded the maximum size allowed.
        /// </exception>
        /// <seealso href="http://docs.aws.amazon.com/goto/WebAPI/apigatewaymanagementapi-2018-11-29/PostToConnection">REST API Reference for PostToConnection Operation</seealso>
        public virtual PostToConnectionResponse PostToConnection(PostToConnectionRequest request)
        {
            var options = new InvokeOptions();

            options.RequestMarshaller    = PostToConnectionRequestMarshaller.Instance;
            options.ResponseUnmarshaller = PostToConnectionResponseUnmarshaller.Instance;

            return(Invoke <PostToConnectionResponse>(request, options));
        }
コード例 #8
0
        private async Task <APIGatewayProxyResponse> _broadcast(ScanResponse list, AmazonApiGatewayManagementApiClient apiClient, MemoryStream stream, ILambdaContext context)
        {
            var count = 0;

            foreach (var item in list.Items)
            {
                var connectionId = item[Constants.ConnectionIdField].S;

                var postConnectionRequest = new PostToConnectionRequest
                {
                    ConnectionId = connectionId,
                    Data         = stream
                };

                try
                {
                    LambdaLogger.Log($"Post to connection {count}: {connectionId}");
                    stream.Position = 0;
                    await apiClient.PostToConnectionAsync(postConnectionRequest);

                    count++;
                }
                catch (AmazonServiceException e)
                {
                    // API Gateway returns a status of 410 GONE when the connection is no
                    // longer available. If this happens, we simply delete the identifier
                    // from our DynamoDB table.
                    if (e.StatusCode == HttpStatusCode.Gone)
                    {
                        var ddbDeleteRequest = new DeleteItemRequest
                        {
                            TableName = Constants.WEBSOCKET_TABLE,
                            Key       = new Dictionary <string, AttributeValue>
                            {
                                { Constants.ConnectionIdField, new AttributeValue {
                                      S = connectionId
                                  } }
                            }
                        };

                        context.Logger.LogLine($"Deleting gone connection: {connectionId}");
                        await _ddbClient.DeleteItemAsync(ddbDeleteRequest);
                    }
                    else
                    {
                        context.Logger.LogLine($"Error posting message to {connectionId}: {e.Message}");
                        context.Logger.LogLine(e.StackTrace);
                    }
                }
            }

            return(new APIGatewayProxyResponse
            {
                StatusCode = 200,
                Body = "Data send to " + count + " connection" + (count == 1 ? "" : "s")
            });
        }
コード例 #9
0
        public async Task FunctionHandler(KinesisEvent kinesisEvent, ILambdaContext context)
        {
            context.Logger.LogLine($"Beginning to process {kinesisEvent.Records.Count} records...");

            var table    = Table.LoadTable(_dynamoDb, Constants.TableName);
            var scanResp = await _dynamoDb.ScanAsync(new ScanRequest()
            {
                TableName            = Constants.TableName,
                ProjectionExpression = Constants.ConnectionIdField
            });

            foreach (var record in kinesisEvent.Records)
            {
                context.Logger.LogLine($"Event ID: {record.EventId}");
                context.Logger.LogLine($"Event Name: {record.EventName}");

                string recordData = GetRecordContents(record.Kinesis);
                context.Logger.LogLine($"Record Data:");
                context.Logger.LogLine(recordData);

                var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(recordData));

                foreach (var item in scanResp.Items)
                {
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Position = 0;

                    var connectionId          = item[Constants.ConnectionIdField].S;
                    var postConnectionRequest = new PostToConnectionRequest()
                    {
                        ConnectionId = connectionId,
                        Data         = stream
                    };

                    try
                    {
                        await _apiClient.PostToConnectionAsync(postConnectionRequest);
                    }
                    catch (AmazonServiceException e)
                    {
                        if (e.StatusCode == HttpStatusCode.Gone)
                        {
                            await table.DeleteItemAsync(connectionId);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }

            context.Logger.LogLine("Stream processing complete.");
        }
コード例 #10
0
        private async Task <APIGatewayProxyResponse> _broadcast(List <WSConnection> list, AmazonApiGatewayManagementApiClient client, MemoryStream stream)
        {
            var count = 0;

            foreach (var item in list)
            {
                var connectionId          = item.connectionId;
                var postConnectionRequest = new PostToConnectionRequest
                {
                    ConnectionId = connectionId,
                    Data         = stream
                };

                try
                {
                    LambdaLogger.Log($"Post to connection {count}: {connectionId}");
                    stream.Position = 0;
                    await client.PostToConnectionAsync(postConnectionRequest);

                    count++;
                }
                catch (AmazonServiceException e)
                {
                    LambdaLogger.Log($"Connection had appeared to have a problem! " + e.StatusCode);
                    // API Gateway returns a status of 410 GONE when the connection is no
                    // longer available. If this happens, we simply delete the identifier
                    // from our DynamoDB table.
                    if (e.StatusCode == HttpStatusCode.Gone)
                    {
                        var wsConnection = new WSConnection();
                        wsConnection.connectionId = connectionId;
                        LambdaLogger.Log($"Deleting gone connection: {connectionId}");
                        await wsdm.deleteSubcriber(wsConnection);
                    }
                    else
                    {
                        var wsConnection = new WSConnection();
                        wsConnection.connectionId = connectionId;
                        LambdaLogger.Log($"Deleting invalid connection: {connectionId}");
                        await wsdm.deleteSubcriber(wsConnection);

                        LambdaLogger.Log(e.StackTrace);
                        //LambdaLogger.Log($"Error posting message to {connectionId}: {e.Message}");
                    }
                }
            }

            return(new APIGatewayProxyResponse
            {
                StatusCode = 200,
                Body = "Connected."
            });
        }
コード例 #11
0
        internal static void SendCatchup(string serviceUrl, string connectionId, string room, JArray messages)
        {
            JObject message = new JObject()
            {
                { "action", "catchup" }, { "room", room }, { "messages", messages }
            };
            MemoryStream stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(message.ToString(Newtonsoft.Json.Formatting.None)));
            AmazonApiGatewayManagementApiConfig config = new AmazonApiGatewayManagementApiConfig()
            {
                ServiceURL = serviceUrl
            };
            AmazonApiGatewayManagementApiClient client  = new AmazonApiGatewayManagementApiClient(config);
            PostToConnectionRequest             postReq = new PostToConnectionRequest()
            {
                ConnectionId = connectionId, Data = stream
            };

            client.PostToConnectionAsync(postReq);
        }
コード例 #12
0
        public static void SendPosition(ProxyRequestContext context, string contractId)
        {
            Asset    asset    = new Asset();
            Document document = asset.getItem(contractId);
            AmazonApiGatewayManagementApiClient client = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig()
            {
                ServiceURL = "https://" + context.DomainName + "/" + context.Stage
            });

            MemoryStream            stream      = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(document)));
            PostToConnectionRequest postRequest = new PostToConnectionRequest()
            {
                ConnectionId = context.ConnectionId,
                Data         = stream
            };

            var result = client.PostToConnectionAsync(postRequest);

            result.Wait();
        }
コード例 #13
0
        private async Task SendJson(ChatSession session, object json)
        {
            var request = new PostToConnectionRequest
            {
                ConnectionId = session.ConnectionId,
                Data         = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(json)))
            };

            try
            {
                await gateway.PostToConnectionAsync(request);
            }
            catch (GoneException)
            {
                // Delete this connection if it wasn't updated
                var deleteRequest = new DeleteItemRequest
                {
                    Key                      = ChatSession.ToKey(session),
                    TableName                = SessionTable,
                    ConditionExpression      = "#Connection = :connectionId",
                    ExpressionAttributeNames = new Dictionary <string, string>
                    {
                        { "#Connection", ChatSession.ConnectionAttribute }
                    },
                    ExpressionAttributeValues = new Dictionary <string, AttributeValue>
                    {
                        { ":connectionId", new AttributeValue(session.ConnectionId) }
                    }
                };

                try
                {
                    await dynamo.DeleteItemAsync(deleteRequest);
                }
                catch (ConditionalCheckFailedException)
                {
                    // Do nothing, the connection was since updated
                }
            }
        }
コード例 #14
0
        public async void NotifyMessageUpdates_SendsProperMessage()
        {
            var message = new Message
            {
                ClientId = "foo",
                MsgText  = "bar"
            };

            var update = CreateDynamoEvent(message);
            var expectedWebSocketConnections = new List <WebSocketConnection>
            {
                new WebSocketConnection
                {
                    ConnectionId = "some connection id"
                }
            };

            var asyncSearch = new Mock <IAsyncSearchWrapper <WebSocketConnection> >();

            asyncSearch.Setup(x => x.GetRemainingAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(expectedWebSocketConnections);
            _dynamoDbContextWrapper.Setup(x => x.QueryAsync <WebSocketConnection>("true", null))
            .Returns(asyncSearch.Object);

            PostToConnectionRequest postRequest = null;

            _apiGatewayManagementApi.Setup(x => x.PostToConnectionAsync(
                                               It.IsAny <PostToConnectionRequest>(),
                                               It.IsAny <CancellationToken>()))
            .Callback <PostToConnectionRequest, CancellationToken>((r, _) => postRequest = r)
            .ReturnsAsync(new PostToConnectionResponse());

            await _testObject.NotifyMessageUpdate(update, new TestLambdaContext());

            var data = Encoding.UTF8.GetString(postRequest.Data.ToArray());

            Assert.Equal(JsonConvert.SerializeObject(message, new JsonSerializerSettings {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }), data);
        }
コード例 #15
0
ファイル: Functions.cs プロジェクト: aws/aws-lambda-dotnet
        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.LogLine($"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))
                {
                    context.Logger.LogLine("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.LogLine($"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.LogLine($"Deleting gone connection: {postConnectionRequest.ConnectionId}");
                            await DDBClient.DeleteItemAsync(ddbDeleteRequest);
                        }
                        else
                        {
                            context.Logger.LogLine($"Error posting message to {postConnectionRequest.ConnectionId}: {e.Message}");
                            context.Logger.LogLine(e.StackTrace);
                        }
                    }
                }

                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.OK,
                    Body = "Data sent to " + count + " connection" + (count == 1 ? "" : "s")
                });
            }
            catch (Exception e)
            {
                context.Logger.LogLine("Error disconnecting: " + e.Message);
                context.Logger.LogLine(e.StackTrace);
                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError,
                    Body = $"Failed to send message: {e.Message}"
                });
            }
        }
コード例 #16
0
ファイル: Echo.cs プロジェクト: GavL89/apigw-websockets-net
        public async Task <APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
        {
            LambdaLogger.Log(JObject.FromObject(request).ToString());

            try
            {
                var domainName = request.RequestContext.DomainName;
                var stage      = request.RequestContext.Stage;
                var endpoint   = $"https://{domainName}/{stage}";
                LambdaLogger.Log("API Gateway management endpoint:" + endpoint);

                var message = JsonConvert.DeserializeObject <JObject>(request.Body);
                var data    = message["data"]?.ToString();

                var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data));

                var scanRequest = new ScanRequest
                {
                    TableName            = Environment.GetEnvironmentVariable("DynamoChatTable"),
                    ProjectionExpression = "ConnectionId"
                };

                var scanResponse = await ddbClient.ScanAsync(scanRequest);

                var apiClient = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig
                {
                    ServiceURL = endpoint
                });

                var count = 0;
                foreach (var item in scanResponse.Items)
                {
                    var connectionId = item["ConnectionId"].S;


                    var postConnectionRequest = new PostToConnectionRequest
                    {
                        ConnectionId = connectionId,
                        Data         = stream
                    };

                    try
                    {
                        context.Logger.LogLine($"Post to connection {count}: {connectionId}");
                        stream.Position = 0;
                        await apiClient.PostToConnectionAsync(postConnectionRequest);

                        count++;
                    }
                    catch (AmazonServiceException e)
                    {
                        // API Gateway returns a status of 410 GONE when the connection is no
                        // longer available. If this happens, we simply delete the identifier
                        // from our DynamoDB table.
                        if (e.StatusCode == HttpStatusCode.Gone)
                        {
                            var ddbDeleteRequest = new DeleteItemRequest
                            {
                                TableName = Environment.GetEnvironmentVariable("DynamoChatTable"),
                                Key       = new Dictionary <string, AttributeValue>
                                {
                                    { "ConnectionId", new AttributeValue {
                                          S = connectionId
                                      } }
                                }
                            };

                            context.Logger.LogLine($"Deleting gone connection: {connectionId}");
                            await ddbClient.DeleteItemAsync(ddbDeleteRequest);
                        }
                        else
                        {
                            context.Logger.LogLine($"Error posting message to {connectionId}: {e.Message}");
                            context.Logger.LogLine(e.StackTrace);
                        }
                    }
                }

                return(new APIGatewayProxyResponse
                {
                    StatusCode = 200,
                    Body = "Data send to " + count + " connection" + (count == 1 ? "" : "s")
                });
            }
            catch (Exception e)
            {
                LambdaLogger.Log("Error disconnecting: " + e.Message);
                LambdaLogger.Log(e.StackTrace);
                return(new APIGatewayProxyResponse
                {
                    StatusCode = 500,
                    Body = $"Failed to send message: {e.Message}"
                });
            }
        }
コード例 #17
0
ファイル: Function.cs プロジェクト: ludoguer/BlazorVotingDemo
        public async Task <APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
        {
            try
            {
                var domainName = request.RequestContext.DomainName;
                var stage      = request.RequestContext.Stage;
                var endpoint   = $"https://{domainName}/{stage}";
                context.Logger.LogLine($"API Gateway management endpoint: {endpoint}");

                var message = JsonConvert.DeserializeObject <JObject>(request.Body);
                var data    = message["data"]?.ToString();

                var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data));

                var scanRequest = new ScanRequest
                {
                    TableName            = Constants.TABLE_NAME,
                    ProjectionExpression = Constants.ConnectionIdField
                };

                var scanResponse = await _ddbClient.ScanAsync(scanRequest);

                var apiClient = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig
                {
                    ServiceURL = endpoint
                });

                var count = 0;
                foreach (var item in scanResponse.Items)
                {
                    var connectionId = item[Constants.ConnectionIdField].S;

                    var postConnectionRequest = new PostToConnectionRequest
                    {
                        ConnectionId = connectionId,
                        Data         = stream
                    };

                    try
                    {
                        context.Logger.LogLine($"Post to connection {count}: {connectionId}");
                        stream.Position = 0;
                        await apiClient.PostToConnectionAsync(postConnectionRequest);

                        count++;
                    }
                    catch (AmazonServiceException e)
                    {
                        if (e.StatusCode == HttpStatusCode.Gone)
                        {
                            var ddbDeleteRequest = new DeleteItemRequest
                            {
                                TableName = Constants.TABLE_NAME,
                                Key       = new Dictionary <string, AttributeValue>
                                {
                                    { Constants.ConnectionIdField, new AttributeValue {
                                          S = connectionId
                                      } }
                                }
                            };

                            context.Logger.LogLine($"Deleting gone connection: {connectionId}");
                            await _ddbClient.DeleteItemAsync(ddbDeleteRequest);
                        }
                        else
                        {
                            context.Logger.LogLine($"Error posting message to {connectionId}: {e.Message}");
                            context.Logger.LogLine(e.StackTrace);
                        }
                    }
                }

                return(new APIGatewayProxyResponse
                {
                    StatusCode = 200,
                    Body = "Data send to " + count + " connection" + (count == 1 ? "" : "s")
                });
            }
            catch (Exception e)
            {
                context.Logger.LogLine("Error disconnecting: " + e.Message);
                context.Logger.LogLine(e.StackTrace);
                return(new APIGatewayProxyResponse
                {
                    StatusCode = 500,
                    Body = $"Failed to send message: {e.Message}"
                });
            }
        }
コード例 #18
0
ファイル: SendMessage.cs プロジェクト: daviddw/aws-ws-2
        public async Task <APIGatewayProxyResponse> Handler(APIGatewayProxyRequest input, ILambdaContext context)
        {
            var client = new AmazonDynamoDBClient();

            var scanRequest = new ScanRequest
            {
                TableName            = Environment.ExpandEnvironmentVariables("%TABLE_NAME%"),
                ProjectionExpression = "connectionId"
            };

            ScanResponse connections = null;

            try
            {
                connections = await client.ScanAsync(scanRequest);
            }
            catch (Exception e)
            {
                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError,
                    Body = e.Message,
                    Headers = new Dictionary <string, string> {
                        { "Content-Type", "text/plain" }
                    },
                });
            }

            var data      = JObject.Parse(input.Body)["data"].ToString();
            var byteArray = Encoding.UTF8.GetBytes(data);

            var config = new AmazonApiGatewayManagementApiConfig
            {
                ServiceURL = $"https://{input.RequestContext.DomainName}/{input.RequestContext.Stage}"
            };

            var apiClient = new AmazonApiGatewayManagementApiClient(config);

            var connectionIds = connections.Items.Select(item => item["connectionId"].S).ToList();

            foreach (var connectionId in connectionIds)
            {
                var postData = new MemoryStream(byteArray);

                try
                {
                    var postToRequest = new PostToConnectionRequest
                    {
                        ConnectionId = connectionId,
                        Data         = postData
                    };

                    await apiClient.PostToConnectionAsync(postToRequest);
                }
                catch (GoneException)
                {
                    Console.WriteLine($"Found dead connection, deleting {connectionId}");

                    var attributes = new Dictionary <string, AttributeValue>();

                    attributes["connectionId"] = new AttributeValue {
                        S = connectionId
                    };

                    var deleteRequest = new DeleteItemRequest
                    {
                        TableName = Environment.ExpandEnvironmentVariables("%TABLE_NAME%"),
                        Key       = attributes
                    };

                    try
                    {
                        await client.DeleteItemAsync(deleteRequest);
                    }
                    catch (Exception e)
                    {
                        return(new APIGatewayProxyResponse
                        {
                            StatusCode = (int)HttpStatusCode.InternalServerError,
                            Body = e.Message,
                            Headers = new Dictionary <string, string> {
                                { "Content-Type", "text/plain" }
                            },
                        });
                    }
                }
                catch (Exception e)
                {
                    return(new APIGatewayProxyResponse
                    {
                        StatusCode = (int)HttpStatusCode.InternalServerError,
                        Body = e.Message,
                        Headers = new Dictionary <string, string> {
                            { "Content-Type", "text/plain" }
                        },
                    });
                }
            }

            return(new APIGatewayProxyResponse
            {
                StatusCode = (int)HttpStatusCode.OK,
                Body = "data sent",
                Headers = new Dictionary <string, string> {
                    { "Content-Type", "text/plain" }
                },
            });
        }
コード例 #19
0
        public async Task <APIGatewayProxyResponse> PingPongHandler(APIGatewayProxyRequest request, ILambdaContext context)
        {
            try
            {
                var domainName = request.RequestContext.DomainName;
                var stage      = request.RequestContext.Stage;
                var endpoint   = $"https://{domainName}/{stage}";
                var apiClient  = ApiGatewayManagementApiClientFactory(endpoint);

                context.Logger.LogLine($"API Gateway management endpoint: {endpoint}");

                var connectionId = request.RequestContext.ConnectionId;
                context.Logger.LogLine($"Ping from ConnectionId: {connectionId}");



                var stream = new MemoryStream(Encoding.UTF8.GetBytes("{\"message\": \"pong\"}"));
                var postConnectionRequest = new PostToConnectionRequest
                {
                    ConnectionId = connectionId,
                    Data         = stream
                };

                try
                {
                    context.Logger.LogLine($"Reply pong to connection: {postConnectionRequest.ConnectionId}");
                    stream.Position = 0;
                    await apiClient.PostToConnectionAsync(postConnectionRequest);
                }
                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.LogLine($"Deleting gone connection: {postConnectionRequest.ConnectionId}");
                        await DdbClient.DeleteItemAsync(ddbDeleteRequest);
                    }
                    else
                    {
                        context.Logger.LogLine($"Error posting message to {postConnectionRequest.ConnectionId}: {e.Message}");
                        context.Logger.LogLine(e.StackTrace);
                    }
                }

                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.OK,
                    Body = $"Pong sent to connection id {connectionId}"
                });
            }
            catch (Exception e)
            {
                context.Logger.LogLine("Error ping/pong: " + e.Message);
                context.Logger.LogLine(e.StackTrace);
                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError,
                    Body = $"Failed to send message: {e.Message}"
                });
            }
        }
コード例 #20
0
ファイル: Functions.cs プロジェクト: rottenmonday/CHMURY
        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}";
                var connectionId = request.RequestContext.ConnectionId;
                context.Logger.LogLine($"API Gateway management endpoint: {endpoint}");

                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))
                {
                    context.Logger.LogLine("Failed to find data element in JSON document");
                    return(new APIGatewayProxyResponse
                    {
                        StatusCode = (int)HttpStatusCode.BadRequest
                    });
                }
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true,
                };
                ChatMessageRequest messageRequest = JsonSerializer.Deserialize <ChatMessageRequest>(dataProperty.ToString(), options);
                string             date           = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds.ToString();
                await DDBUtils.PutMessage(messageRequest.Message, messageRequest.RoomID, messageRequest.UserID, date);

                ChatMessageResponse chatMsg = new ChatMessageResponse
                {
                    Success = true,
                    Message = messageRequest.Message,
                    Date    = date,
                    Author  = messageRequest.UserID,
                    RoomId  = messageRequest.RoomID
                };

                string data   = JsonSerializer.Serialize(chatMsg);
                var    stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data));

                var queryRequest = new QueryRequest
                {
                    TableName = RoomsConnectionsTable,
                    KeyConditionExpression    = "RoomId = :ri",
                    ExpressionAttributeValues = new Dictionary <string, AttributeValue> {
                        { ":ri", new AttributeValue {
                              S = messageRequest.RoomID
                          } }
                    },
                    ProjectionExpression = "RoomId, ConnectionId"
                };

                var queryResponse = await DDBClient.QueryAsync(queryRequest);

                // 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 queryResponse.Items)
                {
                    var postConnectionRequest = new PostToConnectionRequest
                    {
                        ConnectionId = item["ConnectionId"].S,
                        Data         = stream
                    };

                    try
                    {
                        context.Logger.LogLine($"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 = RoomsConnectionsTable,
                                Key       = new Dictionary <string, AttributeValue>
                                {
                                    { "RoomId", new AttributeValue {
                                          S = item["RoomId"].S
                                      } },
                                    { "ConnectionId", new AttributeValue {
                                          S = postConnectionRequest.ConnectionId
                                      } }
                                }
                            };

                            context.Logger.LogLine($"Deleting gone connection: {postConnectionRequest.ConnectionId}");
                            await DDBClient.DeleteItemAsync(ddbDeleteRequest);
                        }
                        else
                        {
                            context.Logger.LogLine($"Error posting message to {postConnectionRequest.ConnectionId}: {e.Message}");
                            context.Logger.LogLine(e.StackTrace);
                        }
                    }
                }

                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.OK,
                    Body = "Data sent to " + count + " connection" + (count == 1 ? "" : "s")
                });
            }
            catch (Exception e)
            {
                context.Logger.LogLine("Error sending message: " + e.Message);
                context.Logger.LogLine(e.StackTrace);
                return(new APIGatewayProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError,
                    Body = $"Failed to send message: {e.Message}"
                });
            }
        }
        public async Task SendMessage(MessageEvent evnt)
        {
            if (string.IsNullOrEmpty(_ddbTableName))
            {
                return;
            }

            var payload = JsonConvert.SerializeObject(evnt);
            var stream  = new MemoryStream(Encoding.UTF8.GetBytes(payload));


            QueryResponse queryResponse;

            if (!_connectionsCache.TryGetValue(evnt.TargetUser, out ICacheEntry entry) ||
                entry.AbsoluteExpiration < DateTime.UtcNow)
            {
                var queryRequest = new QueryRequest
                {
                    TableName = _ddbTableName,
                    IndexName = "username",
                    KeyConditionExpression    = $"{UsernameField} = :u",
                    ExpressionAttributeValues = new Dictionary <string, AttributeValue>
                    {
                        { ":u", new AttributeValue {
                              S = evnt.TargetUser
                          } }
                    }
                };
                queryResponse = await _ddbClient.QueryAsync(queryRequest);

                entry = _connectionsCache.CreateEntry(evnt.TargetUser);
                entry.AbsoluteExpiration = DateTime.UtcNow.AddSeconds(10);
                entry.SetValue(queryResponse);
                _connectionsCache.Set(evnt.TargetUser, entry);
            }
            else
            {
                queryResponse = entry.Value as QueryResponse;
            }

            AmazonApiGatewayManagementApiClient apiClient = null;

            try
            {
                var goneConnections = new List <Dictionary <string, AttributeValue> >();
                foreach (var item in queryResponse.Items)
                {
                    var endpoint = item[EndpointField].S;

                    if (apiClient == null || !apiClient.Config.ServiceURL.Equals(endpoint, StringComparison.Ordinal))
                    {
                        if (apiClient != null)
                        {
                            apiClient.Dispose();
                            apiClient = null;
                        }

                        apiClient = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig
                        {
                            ServiceURL = endpoint
                        });
                    }

                    var connectionId = item[ConnectionIdField].S;

                    stream.Position = 0;
                    var postConnectionRequest = new PostToConnectionRequest
                    {
                        ConnectionId = connectionId,
                        Data         = stream
                    };

                    try
                    {
                        await apiClient.PostToConnectionAsync(postConnectionRequest);
                    }
                    catch (GoneException)
                    {
                        goneConnections.Add(item);
                    }
                }

                // Remove connections from the cache that have disconnected.
                foreach (var goneConnectionItem in goneConnections)
                {
                    queryResponse.Items.Remove(goneConnectionItem);
                }
            }
            catch
            {
                // Never stop rendering based on communication errors.
            }
            finally
            {
                apiClient?.Dispose();
            }
        }