diff --git a/src/GraphQL.Client/GraphQLHttpClientOptions.cs b/src/GraphQL.Client/GraphQLHttpClientOptions.cs index 13a9c576..169260f0 100644 --- a/src/GraphQL.Client/GraphQLHttpClientOptions.cs +++ b/src/GraphQL.Client/GraphQLHttpClientOptions.cs @@ -61,9 +61,17 @@ public class GraphQLHttpClientOptions /// Note that compatible to the draft graphql-over-http spec GraphQL Server MAY return 4xx status codes (401/403, etc.) /// with well-formed GraphQL response containing errors collection. /// - public Func IsValidResponseToDeserialize { get; set; } = r => - // Why not application/json? See https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#processing-the-response - r.IsSuccessStatusCode || r.StatusCode == HttpStatusCode.BadRequest || r.Content.Headers.ContentType?.MediaType == "application/graphql+json"; + public Func IsValidResponseToDeserialize { get; set; } = DefaultIsValidResponseToDeserialize; + + private static readonly IReadOnlyCollection _acceptedResponseContentTypes = new[] { "application/graphql+json", "application/json", "application/graphql-response+json" }; + + public static bool DefaultIsValidResponseToDeserialize(HttpResponseMessage r) + { + if (r.Content.Headers.ContentType?.MediaType != null && !_acceptedResponseContentTypes.Contains(r.Content.Headers.ContentType.MediaType)) + return false; + + return r.IsSuccessStatusCode || r.StatusCode == HttpStatusCode.BadRequest; + } /// /// This callback is called after successfully establishing a websocket connection but before any regular request is made. diff --git a/tests/GraphQL.Client.Serializer.Tests/DefaultValidationTest.cs b/tests/GraphQL.Client.Serializer.Tests/DefaultValidationTest.cs new file mode 100644 index 00000000..861b59b6 --- /dev/null +++ b/tests/GraphQL.Client.Serializer.Tests/DefaultValidationTest.cs @@ -0,0 +1,28 @@ +using System.Net; +using System.Net.Http.Headers; +using FluentAssertions; +using GraphQL.Client.Http; +using Xunit; + +namespace GraphQL.Client.Serializer.Tests; + +public class DefaultValidationTest +{ + [Theory] + [InlineData(HttpStatusCode.OK, "application/json", true)] + [InlineData(HttpStatusCode.OK, "application/graphql-response+json", true)] + [InlineData(HttpStatusCode.BadRequest, "application/json", true)] + [InlineData(HttpStatusCode.BadRequest, "text/html", false)] + [InlineData(HttpStatusCode.OK, "text/html", false)] + [InlineData(HttpStatusCode.Forbidden, "text/html", false)] + [InlineData(HttpStatusCode.Forbidden, "application/json", false)] + public void IsValidResponse_OkJson_True(HttpStatusCode statusCode, string mediaType, bool expectedResult) + { + var response = new HttpResponseMessage(statusCode); + response.Content.Headers.ContentType = new MediaTypeHeaderValue(mediaType); + + bool isValid = new GraphQLHttpClientOptions().IsValidResponseToDeserialize(response); + + isValid.Should().Be(expectedResult); + } +}