Skip to content

Commit ac2043a

Browse files
sungam3rrose-a
andauthored
Allow non-200 HTTP status codes (graphql-dotnet#419)
* Allow non-200 HTTP status codes * Update src/GraphQL.Client/GraphQLHttpClientOptions.cs Co-authored-by: Alexander Rose <[email protected]> * fix Co-authored-by: Alexander Rose <[email protected]>
1 parent 9ca13c2 commit ac2043a

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

src/GraphQL.Client/GraphQLHttpClient.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class GraphQLHttpClient : IGraphQLClient, IDisposable
1111
private readonly Lazy<GraphQLHttpWebSocket> _lazyHttpWebSocket;
1212
private GraphQLHttpWebSocket GraphQlHttpWebSocket => _lazyHttpWebSocket.Value;
1313

14-
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
14+
private readonly CancellationTokenSource _cancellationTokenSource = new();
1515

1616
private readonly bool _disposeHttpClient = false;
1717

@@ -42,14 +42,17 @@ public class GraphQLHttpClient : IGraphQLClient, IDisposable
4242

4343
#region Constructors
4444

45-
public GraphQLHttpClient(string endPoint, IGraphQLWebsocketJsonSerializer serializer) : this(new Uri(endPoint), serializer) { }
45+
public GraphQLHttpClient(string endPoint, IGraphQLWebsocketJsonSerializer serializer)
46+
: this(new Uri(endPoint), serializer) { }
4647

47-
public GraphQLHttpClient(Uri endPoint, IGraphQLWebsocketJsonSerializer serializer) : this(o => o.EndPoint = endPoint, serializer) { }
48+
public GraphQLHttpClient(Uri endPoint, IGraphQLWebsocketJsonSerializer serializer)
49+
: this(o => o.EndPoint = endPoint, serializer) { }
4850

49-
public GraphQLHttpClient(Action<GraphQLHttpClientOptions> configure, IGraphQLWebsocketJsonSerializer serializer) : this(configure.New(), serializer) { }
51+
public GraphQLHttpClient(Action<GraphQLHttpClientOptions> configure, IGraphQLWebsocketJsonSerializer serializer)
52+
: this(configure.New(), serializer) { }
5053

51-
public GraphQLHttpClient(GraphQLHttpClientOptions options, IGraphQLWebsocketJsonSerializer serializer) : this(
52-
options, serializer, new HttpClient(options.HttpMessageHandler))
54+
public GraphQLHttpClient(GraphQLHttpClientOptions options, IGraphQLWebsocketJsonSerializer serializer)
55+
: this(options, serializer, new HttpClient(options.HttpMessageHandler))
5356
{
5457
// set this flag to dispose the internally created HttpClient when GraphQLHttpClient gets disposed
5558
_disposeHttpClient = true;
@@ -120,7 +123,7 @@ private async Task<GraphQLHttpResponse<TResponse>> SendHttpRequestAsync<TRespons
120123

121124
var contentStream = await httpResponseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false);
122125

123-
if (httpResponseMessage.IsSuccessStatusCode)
126+
if (Options.IsValidResponseToDeserialize(httpResponseMessage))
124127
{
125128
var graphQLResponse = await JsonSerializer.DeserializeFromUtf8StreamAsync<TResponse>(contentStream, cancellationToken).ConfigureAwait(false);
126129
return graphQLResponse.ToGraphQLHttpResponse(httpResponseMessage.Headers, httpResponseMessage.StatusCode);
@@ -167,7 +170,7 @@ public void Dispose()
167170
}
168171

169172
private volatile bool _disposed;
170-
private readonly object _disposeLocker = new object();
173+
private readonly object _disposeLocker = new();
171174

172175
protected virtual void Dispose(bool disposing)
173176
{

src/GraphQL.Client/GraphQLHttpClientOptions.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Net;
12
using System.Net.Http.Headers;
23
using System.Net.WebSockets;
34

@@ -16,7 +17,7 @@ public class GraphQLHttpClientOptions
1617
/// <summary>
1718
/// The GraphQL EndPoint to be used for websocket connections
1819
/// </summary>
19-
public Uri? WebSocketEndPoint { get; set; } = null;
20+
public Uri? WebSocketEndPoint { get; set; }
2021

2122
/// <summary>
2223
/// The <see cref="System.Net.Http.HttpMessageHandler"/> that is going to be used
@@ -50,12 +51,17 @@ public class GraphQLHttpClientOptions
5051
Task.FromResult(request is GraphQLHttpRequest graphQLHttpRequest ? graphQLHttpRequest : new GraphQLHttpRequest(request));
5152

5253
/// <summary>
53-
/// This callback is called after successfully establishing a websocket connection but before any regular request is made.
54+
/// Delegate to determine if GraphQL response may be properly deserialized into <see cref="GraphQLResponse{T}"/>.
55+
/// </summary>
56+
public Func<HttpResponseMessage, bool> IsValidResponseToDeserialize { get; set; } = r => r.IsSuccessStatusCode || r.StatusCode == HttpStatusCode.BadRequest;
57+
58+
/// <summary>
59+
/// This callback is called after successfully establishing a websocket connection but before any regular request is made.
5460
/// </summary>
5561
public Func<GraphQLHttpClient, Task> OnWebsocketConnected { get; set; } = client => Task.CompletedTask;
5662

5763
/// <summary>
58-
/// Configure additional websocket options (i.e. headers). This will not be invoked on Windows 7 when targeting .NET Framework 4.x.
64+
/// Configure additional websocket options (i.e. headers). This will not be invoked on Windows 7 when targeting .NET Framework 4.x.
5965
/// </summary>
6066
public Action<ClientWebSocketOptions> ConfigureWebsocketOptions { get; set; } = options => { };
6167

0 commit comments

Comments
 (0)