diff --git a/src/GraphQL.Client/Exceptions/GraphQLHttpException.cs b/src/GraphQL.Client/Exceptions/GraphQLHttpException.cs new file mode 100644 index 00000000..e29d0677 --- /dev/null +++ b/src/GraphQL.Client/Exceptions/GraphQLHttpException.cs @@ -0,0 +1,26 @@ +using System; +using System.Net.Http; + +namespace GraphQL.Client.Exceptions { + + /// + /// An exception thrown on unexpected + /// + public class GraphQLHttpException : Exception { + + /// + /// The + /// + public HttpResponseMessage HttpResponseMessage { get; } + + /// + /// Creates a new instance of + /// + /// The unexpected + public GraphQLHttpException(HttpResponseMessage httpResponseMessage) : base($"Unexpected {nameof(System.Net.Http.HttpResponseMessage)} with code: {httpResponseMessage.StatusCode}") { + this.HttpResponseMessage = httpResponseMessage ?? throw new ArgumentNullException(nameof(httpResponseMessage)); + } + + } + +} diff --git a/src/GraphQL.Client/GraphQLClient.cs b/src/GraphQL.Client/GraphQLClient.cs index 008626c7..2f4177a4 100644 --- a/src/GraphQL.Client/GraphQLClient.cs +++ b/src/GraphQL.Client/GraphQLClient.cs @@ -1,8 +1,10 @@ using System; +using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; +using GraphQL.Client.Exceptions; using GraphQL.Common.Request; using GraphQL.Common.Response; using Newtonsoft.Json; @@ -116,8 +118,9 @@ public async Task GetAsync(GraphQLRequest request) { var queryParamsBuilder = new StringBuilder($"query={request.Query}", 3); if (request.OperationName != null) { queryParamsBuilder.Append($"&operationName={request.OperationName}"); } if (request.Variables != null) { queryParamsBuilder.Append($"&variables={JsonConvert.SerializeObject(request.Variables)}"); } - var httpResponseMessage = await this.httpClient.GetAsync($"{this.Options.EndPoint}?{queryParamsBuilder.ToString()}").ConfigureAwait(false); - return await this.ReadHttpResponseMessageAsync(httpResponseMessage).ConfigureAwait(false); + using (var httpResponseMessage = await this.httpClient.GetAsync($"{this.Options.EndPoint}?{queryParamsBuilder.ToString()}").ConfigureAwait(false)) { + return await this.ReadHttpResponseMessageAsync(httpResponseMessage).ConfigureAwait(false); + } } /// @@ -141,9 +144,10 @@ public async Task PostAsync(GraphQLRequest request) { if (request.Query == null) { throw new ArgumentNullException(nameof(request.Query)); } var graphQLString = JsonConvert.SerializeObject(request, this.Options.JsonSerializerSettings); - var httpContent = new StringContent(graphQLString, Encoding.UTF8, this.Options.MediaType.MediaType); - var httpResponseMessage = await this.httpClient.PostAsync(this.EndPoint, httpContent).ConfigureAwait(false); - return await this.ReadHttpResponseMessageAsync(httpResponseMessage).ConfigureAwait(false); + using (var httpContent = new StringContent(graphQLString, Encoding.UTF8, this.Options.MediaType.MediaType)) + using (var httpResponseMessage = await this.httpClient.PostAsync(this.EndPoint, httpContent).ConfigureAwait(false)) { + return await this.ReadHttpResponseMessageAsync(httpResponseMessage).ConfigureAwait(false); + } } /// @@ -158,8 +162,22 @@ public void Dispose() => /// The Response /// The GrahQLResponse private async Task ReadHttpResponseMessageAsync(HttpResponseMessage httpResponseMessage) { - var resultString = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); - return JsonConvert.DeserializeObject(resultString, this.Options.JsonSerializerSettings); + using (var stream = await httpResponseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false)) + using (var streamReader = new StreamReader(stream)) + using (var jsonTextReader = new JsonTextReader(streamReader)) { + var jsonSerializer = new JsonSerializer { + ContractResolver = this.Options.JsonSerializerSettings.ContractResolver + }; + try { + return jsonSerializer.Deserialize(jsonTextReader); + } + catch (JsonReaderException exception) { + if (httpResponseMessage.IsSuccessStatusCode) { + throw exception; + } + throw new GraphQLHttpException(httpResponseMessage); + } + } } } diff --git a/src/GraphQL.Client/GraphQLClientExtensions.cs b/src/GraphQL.Client/GraphQLClientExtensions.cs index 74741a29..ba6aeb1e 100644 --- a/src/GraphQL.Client/GraphQLClientExtensions.cs +++ b/src/GraphQL.Client/GraphQLClientExtensions.cs @@ -1,4 +1,3 @@ -using System.IO; using System.Threading.Tasks; using GraphQL.Common.Request; using GraphQL.Common.Response; diff --git a/src/GraphQL.Common/Exceptions/GraphQLException.cs b/src/GraphQL.Common/Exceptions/GraphQLException.cs index db043494..5e03a77a 100644 --- a/src/GraphQL.Common/Exceptions/GraphQLException.cs +++ b/src/GraphQL.Common/Exceptions/GraphQLException.cs @@ -17,7 +17,7 @@ public class GraphQLException : Exception { /// Constructor for a GraphQLException /// /// The GraphQL Error - public GraphQLException(GraphQLError graphQLError):base(graphQLError.Message) { + public GraphQLException(GraphQLError graphQLError) : base(graphQLError.Message) { this.GraphQLError = graphQLError; } diff --git a/tests/GraphQL.Client.Tests/BaseGraphQLClientTest.cs b/tests/GraphQL.Client.Tests/BaseGraphQLClientTest.cs index 5fbbd9b0..d7f952cb 100644 --- a/tests/GraphQL.Client.Tests/BaseGraphQLClientTest.cs +++ b/tests/GraphQL.Client.Tests/BaseGraphQLClientTest.cs @@ -2,9 +2,9 @@ namespace GraphQL.Client.Tests { - public abstract class BaseGraphQLClientTest : IDisposable{ + public abstract class BaseGraphQLClientTest : IDisposable { - public GraphQLClient GraphQLClient { get; set; } = new GraphQLClient("https://swapi.apis.guru/"); + protected GraphQLClient GraphQLClient { get; } = new GraphQLClient("https://swapi.apis.guru/"); public void Dispose() => this.GraphQLClient.Dispose();