Skip to content

Commit bbdf13c

Browse files
committed
move APQ code to SendQueryAsync method to allow usage over websocket, too
1 parent d199fce commit bbdf13c

File tree

3 files changed

+46
-48
lines changed

3 files changed

+46
-48
lines changed

src/GraphQL.Client/GraphQLHttpClient.cs

+42-44
Original file line numberDiff line numberDiff line change
@@ -89,57 +89,19 @@ public GraphQLHttpClient(string endPoint, IGraphQLWebsocketJsonSerializer serial
8989

9090
#region IGraphQLClient
9191

92-
/// <inheritdoc />
93-
public async Task<GraphQLResponse<TResponse>> SendQueryAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default)
94-
{
95-
return Options.UseWebSocketForQueriesAndMutations || Options.WebSocketEndPoint is not null && Options.EndPoint is null || Options.EndPoint.HasWebSocketScheme()
96-
? await GraphQlHttpWebSocket.SendRequestAsync<TResponse>(request, cancellationToken).ConfigureAwait(false)
97-
: await SendAPQHttpRequestAsync<TResponse>(request, cancellationToken).ConfigureAwait(false);
98-
}
99-
100-
/// <inheritdoc />
101-
public Task<GraphQLResponse<TResponse>> SendMutationAsync<TResponse>(GraphQLRequest request,
102-
CancellationToken cancellationToken = default)
103-
=> SendQueryAsync<TResponse>(request, cancellationToken);
104-
105-
/// <inheritdoc />
106-
public IObservable<GraphQLResponse<TResponse>> CreateSubscriptionStream<TResponse>(GraphQLRequest request)
107-
=> CreateSubscriptionStream<TResponse>(request, null);
92+
private const int APQ_SUPPORTED_VERSION = 1;
10893

10994
/// <inheritdoc />
110-
public IObservable<GraphQLResponse<TResponse>> CreateSubscriptionStream<TResponse>(GraphQLRequest request, Action<Exception>? exceptionHandler)
111-
{
112-
if (_disposed)
113-
throw new ObjectDisposedException(nameof(GraphQLHttpClient));
114-
115-
var observable = GraphQlHttpWebSocket.CreateSubscriptionStream<TResponse>(request, exceptionHandler);
116-
return observable;
117-
}
118-
119-
#endregion
120-
121-
/// <inheritdoc />
122-
public Task InitializeWebsocketConnection() => GraphQlHttpWebSocket.InitializeWebSocket();
123-
124-
/// <inheritdoc />
125-
public Task SendPingAsync(object? payload) => GraphQlHttpWebSocket.SendPingAsync(payload);
126-
127-
/// <inheritdoc />
128-
public Task SendPongAsync(object? payload) => GraphQlHttpWebSocket.SendPongAsync(payload);
129-
130-
#region Private Methods
131-
132-
private async Task<GraphQLHttpResponse<TResponse>> SendAPQHttpRequestAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default)
95+
public async Task<GraphQLResponse<TResponse>> SendQueryAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default)
13396
{
13497
cancellationToken.ThrowIfCancellationRequested();
13598

136-
var savedQuery = request.Query;
99+
string? savedQuery = request.Query;
137100
bool useAPQ = false;
138101

139102
if (request.Query != null && !_apqDisabledPerSession && Options.EnableAutomaticPersistedQueries(request))
140103
{
141104
// https://www.apollographql.com/docs/react/api/link/persisted-queries/
142-
const int APQ_SUPPORTED_VERSION = 1;
143105
useAPQ = true;
144106
request.Extensions ??= new();
145107
request.Extensions["persistedQuery"] = new Dictionary<string, object>
@@ -150,7 +112,7 @@ private async Task<GraphQLHttpResponse<TResponse>> SendAPQHttpRequestAsync<TResp
150112
request.Query = null;
151113
}
152114

153-
var response = await SendHttpRequestAsync<TResponse>(request, cancellationToken);
115+
var response = await SendQueryInternalAsync<TResponse>(request, cancellationToken);
154116

155117
if (useAPQ)
156118
{
@@ -161,21 +123,57 @@ private async Task<GraphQLHttpResponse<TResponse>> SendAPQHttpRequestAsync<TResp
161123
// Alas, for the first time we did not guess and in vain removed Query, so we return Query and
162124
// send request again. This is one-time "cache miss", not so scary.
163125
request.Query = savedQuery;
164-
return await SendHttpRequestAsync<TResponse>(request, cancellationToken);
126+
return await SendQueryInternalAsync<TResponse>(request, cancellationToken);
165127
}
166128
else
167129
{
168130
// GraphQL server either supports APQ of some other version, or does not support it at all.
169131
// Send a request for the second time. This is better than returning an error. Let the client work with APQ disabled.
170132
_apqDisabledPerSession = Options.DisableAPQ(response);
171133
request.Query = savedQuery;
172-
return await SendHttpRequestAsync<TResponse>(request, cancellationToken);
134+
return await SendQueryInternalAsync<TResponse>(request, cancellationToken);
173135
}
174136
}
175137

176138
return response;
177139
}
178140

141+
/// <inheritdoc />
142+
public Task<GraphQLResponse<TResponse>> SendMutationAsync<TResponse>(GraphQLRequest request,
143+
CancellationToken cancellationToken = default)
144+
=> SendQueryAsync<TResponse>(request, cancellationToken);
145+
146+
/// <inheritdoc />
147+
public IObservable<GraphQLResponse<TResponse>> CreateSubscriptionStream<TResponse>(GraphQLRequest request)
148+
=> CreateSubscriptionStream<TResponse>(request, null);
149+
150+
/// <inheritdoc />
151+
public IObservable<GraphQLResponse<TResponse>> CreateSubscriptionStream<TResponse>(GraphQLRequest request, Action<Exception>? exceptionHandler)
152+
{
153+
if (_disposed)
154+
throw new ObjectDisposedException(nameof(GraphQLHttpClient));
155+
156+
var observable = GraphQlHttpWebSocket.CreateSubscriptionStream<TResponse>(request, exceptionHandler);
157+
return observable;
158+
}
159+
160+
#endregion
161+
162+
/// <inheritdoc />
163+
public Task InitializeWebsocketConnection() => GraphQlHttpWebSocket.InitializeWebSocket();
164+
165+
/// <inheritdoc />
166+
public Task SendPingAsync(object? payload) => GraphQlHttpWebSocket.SendPingAsync(payload);
167+
168+
/// <inheritdoc />
169+
public Task SendPongAsync(object? payload) => GraphQlHttpWebSocket.SendPongAsync(payload);
170+
171+
#region Private Methods
172+
private async Task<GraphQLResponse<TResponse>> SendQueryInternalAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default) =>
173+
Options.UseWebSocketForQueriesAndMutations || Options.WebSocketEndPoint is not null && Options.EndPoint is null || Options.EndPoint.HasWebSocketScheme()
174+
? await GraphQlHttpWebSocket.SendRequestAsync<TResponse>(request, cancellationToken).ConfigureAwait(false)
175+
: await SendHttpRequestAsync<TResponse>(request, cancellationToken).ConfigureAwait(false);
176+
179177
private async Task<GraphQLHttpResponse<TResponse>> SendHttpRequestAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default)
180178
{
181179
var preprocessedRequest = await Options.PreprocessRequest(request, this).ConfigureAwait(false);

src/GraphQL.Client/GraphQLHttpClientOptions.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ public static bool DefaultIsValidResponseToDeserialize(HttpResponseMessage r)
111111
/// A delegate which takes an <see cref="IGraphQLResponse"/> and returns a boolean to disable any future persisted queries for that session.
112112
/// This defaults to disabling on PersistedQueryNotSupported or a 400 or 500 HTTP error.
113113
/// </summary>
114-
public Func<IGraphQLHttpResponse, bool> DisableAPQ { get; set; } = response =>
114+
public Func<IGraphQLResponse, bool> DisableAPQ { get; set; } = response =>
115115
{
116-
return ((int)response.StatusCode >= 400 && (int)response.StatusCode < 600) ||
117-
response.Errors?.Any(error => string.Equals(error.Message, "PersistedQueryNotSupported", StringComparison.CurrentCultureIgnoreCase)) == true;
116+
return response.Errors?.Any(error => string.Equals(error.Message, "PersistedQueryNotSupported", StringComparison.CurrentCultureIgnoreCase)) == true
117+
|| response is IGraphQLHttpResponse httpResponse && (int)httpResponse.StatusCode >= 400 && (int)httpResponse.StatusCode < 600;
118118
};
119119
}

src/GraphQL.Primitives/GraphQLRequest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class GraphQLRequest : Dictionary<string, object>, IEquatable<GraphQLRequ
1616
/// The Query
1717
/// </summary>
1818
[StringSyntax("GraphQL")]
19-
public string Query
19+
public string? Query
2020
{
2121
get => TryGetValue(QUERY_KEY, out object value) ? (string)value : null;
2222
set => this[QUERY_KEY] = value;

0 commit comments

Comments
 (0)