public async Task ExecuteAsync <TEndPoint>(string path, HttpContext context) where TEndPoint : EndPoint { if (context.Request.Path.StartsWithSegments(path + "/getid")) { await ProcessGetId(context); } else if (context.Request.Path.StartsWithSegments(path + "/send")) { await ProcessSend(context); } else { // Get the end point mapped to this http connection var endpoint = (EndPoint)context.RequestServices.GetRequiredService <TEndPoint>(); var format = string.Equals(context.Request.Query["format"], "binary", StringComparison.OrdinalIgnoreCase) ? Format.Binary : Format.Text; // Server sent events transport if (context.Request.Path.StartsWithSegments(path + "/sse")) { // Get the connection state for the current http context var state = GetOrCreateConnection(context); state.Connection.User = context.User; state.Connection.Metadata["transport"] = "sse"; state.Connection.Metadata.Format = format; // TODO: this is wrong. + how does the user add their own metadata based on HttpContext var formatType = (string)context.Request.Query["formatType"]; state.Connection.Metadata["formatType"] = string.IsNullOrEmpty(formatType) ? "json" : formatType; var sse = new ServerSentEvents(state.Connection); await DoPersistentConnection(endpoint, sse, context, state.Connection); _manager.RemoveConnection(state.Connection.ConnectionId); } else if (context.Request.Path.StartsWithSegments(path + "/ws")) { // Get the connection state for the current http context var state = GetOrCreateConnection(context); state.Connection.User = context.User; state.Connection.Metadata["transport"] = "websockets"; state.Connection.Metadata.Format = format; // TODO: this is wrong. + how does the user add their own metadata based on HttpContext var formatType = (string)context.Request.Query["formatType"]; state.Connection.Metadata["formatType"] = string.IsNullOrEmpty(formatType) ? "json" : formatType; var ws = new WebSockets(state.Connection, format); await DoPersistentConnection(endpoint, ws, context, state.Connection); _manager.RemoveConnection(state.Connection.ConnectionId); } else if (context.Request.Path.StartsWithSegments(path + "/poll")) { bool isNewConnection; var state = GetOrCreateConnection(context, out isNewConnection); // TODO: this is wrong. + how does the user add their own metadata based on HttpContext var formatType = (string)context.Request.Query["formatType"]; state.Connection.Metadata["formatType"] = string.IsNullOrEmpty(formatType) ? "json" : formatType; // Mark the connection as active state.Active = true; RegisterLongPollingDisconnect(context, state.Connection); var longPolling = new LongPolling(state.Connection); // Start the transport var transportTask = longPolling.ProcessRequestAsync(context); Task endpointTask = null; // Raise OnConnected for new connections only since polls happen all the time if (isNewConnection) { state.Connection.Metadata["transport"] = "poll"; state.Connection.Metadata.Format = format; state.Connection.User = context.User; // REVIEW: This is super gross, this all needs to be cleaned up... state.Close = async() => { state.Connection.Channel.Dispose(); await endpointTask; }; endpointTask = endpoint.OnConnectedAsync(state.Connection); state.Connection.Metadata["endpoint"] = endpointTask; } else { // Get the endpoint task from connection state endpointTask = state.Connection.Metadata.Get <Task>("endpoint"); } var resultTask = await Task.WhenAny(endpointTask, transportTask); if (resultTask == endpointTask) { // Notify the long polling transport to end state.Connection.Channel.Dispose(); await transportTask; } // Mark the connection as inactive state.LastSeen = DateTimeOffset.UtcNow; state.Active = false; } } }