graphql-dotnet / graphql-client

A GraphQL Client for .NET Standard
MIT License
625 stars 134 forks source link

AppSync's WS connection closing at initialization #620

Open jonathantsao opened 9 months ago

jonathantsao commented 9 months ago

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();
    }

@rose-a would you happen to know? Perhaps there is something obvious that I am missing in the configuration or suggestion on how to debug the connection failure.

hubaozhang2000 commented 2 months ago

@jonathantsao @rose-a

I have the same issue. WebSocket in GraphQL.Client only works for version 5.1.1 and lower. If I use GraphQL.Client version higher than 5.1.1 , I have the same error message.

Some thing changed from 5.1.1 to 6.0.0 causes the issue.

I cannot upgrade the GraphQL.Client now.

The exception occurs on the line

await client.InitializeWebsocketConnection();