Skip to content

Commit

Permalink
Improve default IsValidResponseToDeserialize implementation (#560)
Browse files Browse the repository at this point in the history
* change default implementation of response validation method to ensure correct response content type

* add tests for the default validation method

* remove unnecessary comments

Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>

* accepted response types private, formatting

* make DefaultIsValidResponseToDeserialize publicly accessible

Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>

* AcceptedResponseContentTypes as static field

---------

Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
  • Loading branch information
mikocot and sungam3r authored May 8, 2023
1 parent 8210ac3 commit f1a5bf8
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
14 changes: 11 additions & 3 deletions src/GraphQL.Client/GraphQLHttpClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
public Func<HttpResponseMessage, bool> 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<HttpResponseMessage, bool> IsValidResponseToDeserialize { get; set; } = DefaultIsValidResponseToDeserialize;

private static readonly IReadOnlyCollection<string> _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;
}

/// <summary>
/// This callback is called after successfully establishing a websocket connection but before any regular request is made.
Expand Down
28 changes: 28 additions & 0 deletions tests/GraphQL.Client.Serializer.Tests/DefaultValidationTest.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit f1a5bf8

Please sign in to comment.