/// <summary> /// Handles the MessageRecieved event of the ApolloClient control. The client raises this event /// whenever a message is recieved and successfully parsed from the under lying websocket. /// </summary> /// <param name="message">The message.</param> /// <returns>TaskMethodBuilder.</returns> internal Task DispatchMessage(ApolloMessage message) { if (message == null) { return(Task.CompletedTask); } _logger?.MessageReceived(message); switch (message.Type) { case ApolloMessageType.CONNECTION_INIT: return(this.AcknowledgeNewConnection()); case ApolloMessageType.START: return(this.ExecuteStartRequest(message as ApolloClientStartMessage)); case ApolloMessageType.STOP: return(this.ExecuteStopRequest(message as ApolloClientStopMessage)); case ApolloMessageType.CONNECTION_TERMINATE: return(this.CloseConnection( ClientConnectionCloseStatus.NormalClosure, $"Recieved closure request via message '{ApolloMessageTypeExtensions.Serialize(ApolloMessageType.CONNECTION_TERMINATE)}'.")); default: return(this.UnknownMessageRecieved(message)); } }
/// <summary> /// Serializes, encodes and sends the given message down to the client. /// </summary> /// <param name="message">The message to send.</param> /// <returns>Task.</returns> public Task SendMessage(ApolloMessage message) { Validation.ThrowIfNull(message, nameof(message)); // create and register the proper serializer for this message var options = new JsonSerializerOptions(); (var converter, var asType) = _messageConverter.CreateConverter <TSchema>(this, message); options.Converters.Add(converter); // graphql is defined to communcate in UTF-8, serialize the result to that var bytes = JsonSerializer.SerializeToUtf8Bytes(message, asType, options); if (this.State == ClientConnectionState.Open) { _logger?.MessageSent(message); return(_connection.SendAsync( new ArraySegment <byte>(bytes, 0, bytes.Length), ClientMessageType.Text, true, default)); } else { return(Task.CompletedTask); } }
/// <summary> /// Returns a generic error to the client indicating that the last message recieved was unknown or invalid. /// </summary> /// <param name="lastMessage">The last message that was received that was unprocessable.</param> /// <returns>Task.</returns> private Task UnknownMessageRecieved(ApolloMessage lastMessage) { var apolloError = new ApolloServerErrorMessage( "The last message recieved was unknown or could not be processed " + "by this server. This graph ql is configured to use Apollo's GraphQL over websockets " + "message schema.", Constants.ErrorCodes.BAD_REQUEST, lastMessage: lastMessage, clientProvidedId: lastMessage.Id); apolloError.Payload.MetaData.Add( Constants.Messaging.REFERENCE_RULE_NUMBER, "Unknown Message Type"); apolloError.Payload.MetaData.Add( Constants.Messaging.REFERENCE_RULE_URL, "https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md"); return(this.SendMessage(apolloError)); }
/// <summary> /// Simulates a client message being sent to the server. /// </summary> /// <param name="message">The message.</param> public void QueueClientMessage(ApolloMessage message) { Validation.ThrowIfNull(message, nameof(message)); this.QueueClientMessage(new MockClientMessage(message)); }
/// <summary> /// Recorded when the configured client proxy sends a message downstream to the /// actual client. /// </summary> /// <param name="message">The message that was sent.</param> public void MessageSent(ApolloMessage message) { _logger.Log( LogLevel.Trace, () => new ApolloClientMessageSentLogEntry(_client, message)); }