Skip to content

Commit ac0b728

Browse files
committed
create client with DelegatingHandler
1 parent 24df130 commit ac0b728

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Net.Http;
3+
using System.Reflection;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
namespace Dubstep.TestUtilities
8+
{
9+
internal class HttpClientWrapHandler : DelegatingHandler
10+
{
11+
private HttpClient _httpClient;
12+
public HttpClientWrapHandler(HttpClient httpClient, HttpMessageHandler innerHandler)
13+
{
14+
_httpClient = httpClient;
15+
InnerHandler = innerHandler;
16+
}
17+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
18+
{
19+
var source = new CancellationTokenSource();
20+
var cancelledToken = source.Token;
21+
source.Cancel();
22+
try
23+
{
24+
await base.SendAsync(request, cancelledToken);
25+
}
26+
catch { }
27+
28+
// Reset the request status and send it again with the inner httpClient
29+
ResetSendStatus(request);
30+
return await _httpClient.SendAsync(request, cancellationToken);
31+
}
32+
33+
private void ResetSendStatus(HttpRequestMessage request)
34+
{
35+
// https://stackoverflow.com/a/43512592/553073
36+
var SEND_STATUS_FIELD_NAME = "_sendStatus";
37+
var requestType = request.GetType().GetTypeInfo();
38+
var sendStatusField = requestType.GetField(SEND_STATUS_FIELD_NAME, BindingFlags.Instance | BindingFlags.NonPublic);
39+
if (sendStatusField != null)
40+
sendStatusField.SetValue(request, 0);
41+
else
42+
throw new Exception($"Failed to hack HttpRequestMessage, {SEND_STATUS_FIELD_NAME} doesn't exist.");
43+
}
44+
}
45+
}

src/TestServer/TestServer.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ public TestServer()
1818
/// Generate a HttpClient instance
1919
/// </summary>
2020
public HttpClient CreateClient()
21+
{
22+
return CreateClient(null);
23+
}
24+
25+
/// <summary>
26+
/// Generate a HttpClient instance and applies additional DelegatingHandler on this client instance
27+
/// </summary>
28+
public HttpClient CreateClient(DelegatingHandler handler)
2129
{
2230
var builder = new WebHostBuilder()
2331
.ConfigureServices(services =>
@@ -26,7 +34,19 @@ public HttpClient CreateClient()
2634
})
2735
.UseStartup<Startup>();
2836
var testServer = new InternalTestServer(builder);
29-
return testServer.CreateClient();
37+
var innerHttpClient = testServer.CreateClient();
38+
39+
if (handler == null)
40+
{
41+
return innerHttpClient;
42+
}
43+
44+
var httpMessageHandler = new HttpClientWrapHandler(innerHttpClient, handler);
45+
var httpClient = new HttpClient(httpMessageHandler)
46+
{
47+
BaseAddress = innerHttpClient.BaseAddress
48+
};
49+
return httpClient;
3050
}
3151
}
3252
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Net.Http;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Dubstep.TestUtilities.Tests
6+
{
7+
/// <summary>
8+
/// A dummy http message handler for testing purpose
9+
/// </summary>
10+
internal class AddUserAgentHandler : DelegatingHandler
11+
{
12+
public AddUserAgentHandler()
13+
{
14+
InnerHandler = new HttpClientHandler();
15+
}
16+
public static string DefaultUserAgent => nameof(AddUserAgentHandler);
17+
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
18+
{
19+
request.Headers.Add("User-Agent", DefaultUserAgent);
20+
return base.SendAsync(request, cancellationToken);
21+
}
22+
}
23+
}

test/TestServer.Tests/TestServerTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,5 +276,26 @@ public async Task WhenMutipleRulesMatched_ShouldActionOnFirstMatch()
276276
// Assert
277277
AssertOkResponse(actual, firstResponse);
278278
}
279+
280+
[Test]
281+
public async Task WhenHaveDelegatingHandler_ShouldApplyToClient()
282+
{
283+
// Arrange
284+
var expectedUserAgent = AddUserAgentHandler.DefaultUserAgent;
285+
286+
_server.CurrentRuleSet
287+
.AddRule()
288+
.WhenPost()
289+
.WhenHeaderMatch("User-Agent", expectedUserAgent)
290+
.SetOkResponse(_okResponse);
291+
// AddUserAgentHandler adds http header User-Agent
292+
var client = _server.CreateClient(new AddUserAgentHandler());
293+
294+
// Act
295+
var actual = await client.PostAsync("/", new StringContent("abcd"));
296+
297+
// Assert
298+
AssertOkResponse(actual);
299+
}
279300
}
280301
}

0 commit comments

Comments
 (0)