Skip to content

Commit 8f2f2bb

Browse files
committed
Add ChainedInterceptor and TestInterceptor for improved request handling
1 parent 7716718 commit 8f2f2bb

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Net;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
4+
namespace GraphQLSharp.Tests;
5+
6+
[TestClass]
7+
public class ChainedInterceptorTests
8+
{
9+
[TestMethod]
10+
public async Task CallInterceptorsInCorrectOrder()
11+
{
12+
var query = """
13+
{
14+
shop
15+
{
16+
id
17+
}
18+
}
19+
""";
20+
21+
var entries = new List<string>();
22+
var options = new GraphQLClientOptions
23+
{
24+
Uri = new Uri("https://example.com/graphql"),
25+
Interceptor = new ChainedInterceptor(
26+
new TestInterceptor(
27+
() => entries.Add("Before1"),
28+
() => entries.Add("After1")))
29+
.Wrap(new TestInterceptor(
30+
() => entries.Add("Before2"),
31+
() => entries.Add("After2")))
32+
.Wrap(new TestInterceptor(
33+
() => entries.Add("Before3"),
34+
() => entries.Add("After3"))),
35+
HttpClient = new HttpClient(new TestHttpMessageHandler(msg =>
36+
{
37+
return new HttpResponseMessage(HttpStatusCode.OK)
38+
{
39+
Content = new StringContent("""{"data":{"shop":{"id":"gid://shopify/Shop/1234567890"}}}""")
40+
};
41+
}))
42+
};
43+
var response = await new GraphQLCLient().ExecuteAsync(query, options);
44+
Assert.AreEqual(HttpStatusCode.OK, response.HttpResponse.StatusCode);
45+
Assert.IsTrue(entries.SequenceEqual(
46+
[
47+
"Before3", "Before2", "Before1",
48+
"After1", "After2", "After3"
49+
]));
50+
}
51+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using GraphQLSharp;
2+
3+
public class TestInterceptor : IInterceptor
4+
{
5+
private readonly Action _onBeforeExecute;
6+
private readonly Action _onAfterExecute;
7+
8+
public TestInterceptor(Action onBeforeExecute, Action onAfterExecute)
9+
{
10+
_onBeforeExecute = onBeforeExecute;
11+
_onAfterExecute = onAfterExecute;
12+
}
13+
14+
public async Task<GraphQLResponse<TData>> InterceptRequestAsync<TGraphQLRequest, TClientOptions, TData>(
15+
TGraphQLRequest request,
16+
TClientOptions defaultOptions,
17+
TClientOptions options,
18+
CancellationToken cancellationToken,
19+
Func<TGraphQLRequest, CancellationToken, Task<GraphQLResponse<TData>>> executeAsync)
20+
where TGraphQLRequest : GraphQLRequest, new()
21+
where TClientOptions : GraphQLClientOptions
22+
{
23+
_onBeforeExecute?.Invoke();
24+
var response = await executeAsync(request, cancellationToken);
25+
_onAfterExecute?.Invoke();
26+
return response;
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace GraphQLSharp;
2+
3+
public class ChainedInterceptor : IInterceptor
4+
{
5+
private List<IInterceptor> _interceptors = new List<IInterceptor>();
6+
7+
public ChainedInterceptor(IInterceptor innerMostInterceptor)
8+
{
9+
this._interceptors.Add(innerMostInterceptor);
10+
}
11+
12+
public ChainedInterceptor Wrap(IInterceptor nextInterceptor)
13+
{
14+
_interceptors.Add(nextInterceptor);
15+
return this;
16+
}
17+
18+
public async Task<GraphQLResponse<TData>> InterceptRequestAsync<TGraphQLRequest, TClientOptions, TData>(TGraphQLRequest request, TClientOptions defaultOptions, TClientOptions options, CancellationToken cancellationToken, Func<TGraphQLRequest, CancellationToken, Task<GraphQLResponse<TData>>> executeAsync)
19+
where TGraphQLRequest : GraphQLRequest, new()
20+
where TClientOptions : GraphQLClientOptions
21+
{
22+
foreach (var interceptor in _interceptors)
23+
{
24+
var capturedInterceptor = interceptor;
25+
var capturedExecuteAsync = executeAsync;
26+
executeAsync = (req, ct) => capturedInterceptor.InterceptRequestAsync(req, defaultOptions, options, ct, capturedExecuteAsync);
27+
}
28+
29+
return await executeAsync(request, cancellationToken);
30+
}
31+
}

0 commit comments

Comments
 (0)