aws / aws-appsync-community

The AWS AppSync community
https://aws.amazon.com/appsync
Apache License 2.0
506 stars 32 forks source link

AppSync's WS connection closing at initialization #350

Open jonathantsao opened 6 months ago

jonathantsao commented 6 months ago

Currently working on a C# client to subscribe to AppSync mutations. I'm trying to follow the example listed in this previously closed issue with my own AppSync setup. However, when the code hits the .InitializeWebSocketConnection, I get a relatively vague WebSocketException saying The remote party closed the WebSocket connection without completing the close handshake. Here is my current code

    public class AppSyncHeader
    {
        [JsonPropertyName("host")]
        public string Host { get; set; }

        [JsonPropertyName("x-api-key")]
        public string ApiKey { get; set; }

        public string ToJson()
        {
            return JsonSerializer.Serialize(this);
        }

        public string ToBase64String()
        {
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(ToJson()));
        }
    }

    public class AuthorizedAppSyncHttpRequest : GraphQLHttpRequest
    {
        private readonly string _authorization;

        public AuthorizedAppSyncHttpRequest(GraphQLRequest request, string authorization) : base(request) =>
            _authorization = authorization;

        public override HttpRequestMessage ToHttpRequestMessage(
            GraphQLHttpClientOptions options,
            IGraphQLJsonSerializer serializer
        )
        {
            HttpRequestMessage result = base.ToHttpRequestMessage(options, serializer);
            result.Headers.Add("X-Api-Key", _authorization);
            return result;
        }
    }

    public static async Task Main(string[] args)
    {
        var regularHost = "xxxxxx.appsync-api.us-east-1.amazonaws.com";
        var wsHost = "xxxxxx.appsync-realtime-api.us-east-1.amazonaws.com";
        var apiKey = "foobar";

        var client = new GraphQLHttpClient(
            $"https://{regularHost}/graphql",
            new SystemTextJsonSerializer(
                new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
            )
        );

        var appSyncHeader = new AppSyncHeader { Host = regularHost, ApiKey = apiKey, };

        string header = appSyncHeader.ToBase64String();

        client.Options.WebSocketEndPoint = new Uri($"wss://{wsHost}/graphql?header={header}&payload=e30=");
        client.Options.PreprocessRequest = (req, client) =>
        {
            GraphQLHttpRequest result = new AuthorizedAppSyncHttpRequest(req, apiKey)
            {
                ["data"] = JsonSerializer.Serialize(req),
                ["extensions"] = new { authorization = appSyncHeader, }
            };
            return Task.FromResult(result);
        };

        await client.InitializeWebsocketConnection();
    }

Would anyone happen to know why the server is rejecting the connection? I was able to test out the endpoint locally with Postman's WebSocket feature and the connection was able to be initialized and was able to start receiving the KA messages.