Skip to content

Commit 78eac27

Browse files
committed
let GraphQLHttpResponse<T> inherit from GraphQLResponse<T>
1 parent 194c152 commit 78eac27

File tree

3 files changed

+42
-61
lines changed

3 files changed

+42
-61
lines changed

src/GraphQL.Client/GraphQLHttpClient.cs

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,10 @@ public GraphQLHttpClient(GraphQLHttpClientOptions options, HttpClient httpClient
6666

6767
/// <inheritdoc />
6868
public async Task<GraphQLResponse<TResponse>> SendQueryAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default) {
69-
if(Options.UseWebSocketForQueriesAndMutations)
69+
if (Options.UseWebSocketForQueriesAndMutations)
7070
return await this.graphQlHttpWebSocket.SendRequest<TResponse>(request, cancellationToken);
71-
72-
var response = await this.SendHttpPostRequestAsync<TResponse>(request, cancellationToken);
73-
return response.Response;
71+
72+
return await this.SendHttpPostRequestAsync<TResponse>(request, cancellationToken);
7473
}
7574

7675
/// <inheritdoc />
@@ -116,47 +115,7 @@ public IObservable<GraphQLResponse<TResponse>> CreateSubscriptionStream<TRespons
116115
/// </summary>
117116
/// <returns></returns>
118117
public Task InitializeWebsocketConnection() => graphQlHttpWebSocket.InitializeWebSocket();
119-
120-
/// <summary>
121-
/// Sends a query to the GraphQL server and deserializes the response. Provides access to the HTTP response headers. This method will never utilize the websocket connection!
122-
/// </summary>
123-
/// <typeparam name="TResponse"></typeparam>
124-
/// <param name="request"></param>
125-
/// <param name="cancellationToken"></param>
126-
/// <returns></returns>
127-
public Task<GraphQLHttpResponse<TResponse>> SendQueryHttpAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default) {
128-
return this.SendHttpPostRequestAsync<TResponse>(request, cancellationToken);
129-
}
130-
/// <inheritdoc cref="SendQueryHttpAsync{TResponse}(GraphQL.GraphQLRequest,System.Threading.CancellationToken)"/>
131-
public Task<GraphQLHttpResponse<TResponse>> SendQueryHttpAsync<TResponse>(GraphQLRequest request,
132-
Func<TResponse> defineResponseType, CancellationToken cancellationToken = default)
133-
=> SendQueryHttpAsync<TResponse>(request, cancellationToken);
134-
/// <inheritdoc cref="SendQueryHttpAsync{TResponse}(GraphQL.GraphQLRequest,System.Threading.CancellationToken)"/>
135-
public Task<GraphQLHttpResponse<TResponse>> SendQueryHttpAsync<TResponse>(string query, object? variables = null,
136-
string? operationName = null, Func<TResponse> defineResponseType = null, CancellationToken cancellationToken = default) {
137-
return SendQueryHttpAsync<TResponse>(new GraphQLRequest(query, variables, operationName), cancellationToken: cancellationToken);
138-
}
139-
140-
/// <summary>
141-
/// Sends a mutation to the GraphQL server and deserializes the response. Provides access to the HTTP response headers. This method will never utilize the websocket connection!
142-
/// </summary>
143-
/// <typeparam name="TResponse"></typeparam>
144-
/// <param name="request"></param>
145-
/// <param name="cancellationToken"></param>
146-
/// <returns></returns>
147-
public Task<GraphQLHttpResponse<TResponse>> SendMutationHttpAsync<TResponse>(GraphQLRequest request,
148-
CancellationToken cancellationToken = default)
149-
=> SendQueryHttpAsync<TResponse>(request, cancellationToken);
150-
/// <inheritdoc cref="SendMutationHttpAsync{TResponse}(GraphQL.GraphQLRequest,System.Threading.CancellationToken)"/>
151-
public Task<GraphQLHttpResponse<TResponse>> SendMutationHttpAsync<TResponse>(GraphQLRequest request,
152-
Func<TResponse> defineResponseType, CancellationToken cancellationToken = default)
153-
=> SendQueryHttpAsync<TResponse>(request, cancellationToken);
154-
/// <inheritdoc cref="SendMutationHttpAsync{TResponse}(GraphQL.GraphQLRequest,System.Threading.CancellationToken)"/>
155-
public Task<GraphQLHttpResponse<TResponse>> SendMutationHttpAsync<TResponse>(string query, object? variables = null,
156-
string? operationName = null, Func<TResponse> defineResponseType = null, CancellationToken cancellationToken = default) {
157-
return SendQueryHttpAsync<TResponse>(new GraphQLRequest(query, variables, operationName), cancellationToken: cancellationToken);
158-
}
159-
118+
160119
#region Private Methods
161120

162121
private async Task<GraphQLHttpResponse<TResponse>> SendHttpPostRequestAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default) {
@@ -166,15 +125,10 @@ private async Task<GraphQLHttpResponse<TResponse>> SendHttpPostRequestAsync<TRes
166125
if (!httpResponseMessage.IsSuccessStatusCode) {
167126
throw new GraphQLHttpException(httpResponseMessage);
168127
}
169-
170-
var response = new GraphQLHttpResponse<TResponse> {
171-
ResponseHeaders = httpResponseMessage.Headers,
172-
StatusCode = httpResponseMessage.StatusCode
173-
};
174128

175129
var bodyStream = await httpResponseMessage.Content.ReadAsStreamAsync();
176-
response.Response = await JsonSerializer.DeserializeFromUtf8StreamAsync<TResponse>(bodyStream, cancellationToken);
177-
return response;
130+
var response = await JsonSerializer.DeserializeFromUtf8StreamAsync<TResponse>(bodyStream, cancellationToken);
131+
return response.ToGraphQLHttpResponse(httpResponseMessage.Headers, httpResponseMessage.StatusCode);
178132
}
179133

180134
private HttpRequestMessage GenerateHttpRequestMessage(GraphQLRequest request) {
Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
1+
using System;
12
using System.Net;
23
using System.Net.Http.Headers;
34

45
namespace GraphQL.Client.Http {
56

6-
public class GraphQLHttpResponse<T> {
7-
public GraphQLHttpResponse()
8-
{
7+
public class GraphQLHttpResponse<T>: GraphQLResponse<T> {
8+
public GraphQLHttpResponse(GraphQLResponse<T> response, HttpResponseHeaders responseHeaders, HttpStatusCode statusCode) {
9+
Data = response.Data;
10+
Errors = response.Errors;
11+
Extensions = response.Extensions;
12+
ResponseHeaders = responseHeaders;
13+
StatusCode = statusCode;
914
}
10-
11-
public GraphQLResponse<T> Response { get; set; }
15+
1216
public HttpResponseHeaders ResponseHeaders { get; set; }
1317
public HttpStatusCode StatusCode { get; set; }
1418
}
19+
20+
public static class GraphQLResponseExtensions {
21+
public static GraphQLHttpResponse<T> ToGraphQLHttpResponse<T>(this GraphQLResponse<T> response, HttpResponseHeaders responseHeaders, HttpStatusCode statusCode) {
22+
return new GraphQLHttpResponse<T>(response, responseHeaders, statusCode);
23+
}
24+
25+
/// <summary>
26+
/// Casts <paramref name="response"/> to <see cref="GraphQLHttpResponse{T}"/>. Throws ig the cast fails.
27+
/// </summary>
28+
/// <typeparam name="T"></typeparam>
29+
/// <param name="response"></param>
30+
/// <exception cref="InvalidCastException"><paramref name="response"/> is not a <see cref="GraphQLHttpResponse{T}"/></exception>
31+
/// <returns></returns>
32+
public static GraphQLHttpResponse<T> AsGraphQLHttpResponse<T>(this GraphQLResponse<T> response) {
33+
return (GraphQLHttpResponse<T>) response;
34+
}
35+
}
1536
}

tests/GraphQL.Integration.Tests/QueryAndMutationTests/Base.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,18 @@ public async void QueryTheory(int id, string name) {
5050

5151
[Theory]
5252
[ClassData(typeof(StarWarsHumans))]
53-
public async void QueryHttpTheory(int id, string name) {
53+
public async void QueryAsHttpResponseTheory(int id, string name) {
5454
var graphQLRequest = new GraphQLRequest($"{{ human(id: \"{id}\") {{ name }} }}");
55-
var httpResponse = await StarWarsClient.SendQueryHttpAsync(graphQLRequest, () => new { Human = new { Name = string.Empty } });
55+
var responseType = new {Human = new {Name = string.Empty}};
56+
var response = await StarWarsClient.SendQueryAsync(graphQLRequest, () => responseType );
5657

57-
httpResponse.Response.Errors.Should().BeNull();
58-
httpResponse.Response.Data.Human.Name.Should().Be(name);
58+
FluentActions.Invoking(() => response.AsGraphQLHttpResponse()).Should()
59+
.NotThrow("because the returned object is a GraphQLHttpResponse");
60+
61+
var httpResponse = response.AsGraphQLHttpResponse();
62+
63+
httpResponse.Errors.Should().BeNull();
64+
httpResponse.Data.Human.Name.Should().Be(name);
5965

6066
httpResponse.StatusCode.Should().BeEquivalentTo(HttpStatusCode.OK);
6167
httpResponse.ResponseHeaders.Date.Should().BeCloseTo(DateTimeOffset.Now, TimeSpan.FromMinutes(1));

0 commit comments

Comments
 (0)