Merge pull request #23 from mikeparker/delegating-handler-support
Add ability to insert delegating handlers into HttpClient
This commit is contained in:
Коммит
63f6ed34df
|
@ -102,7 +102,7 @@ namespace HttpOverStream.Client
|
|||
await request.Content.CopyToAsync(stream).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_logger.LogVerbose("HttpOS Client: stream.FlushAsync");
|
||||
_logger.LogVerbose("HttpOS Client: stream.FlushAsync");
|
||||
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
_logger.LogVerbose("HttpOS Client: Finished writing request");
|
||||
}, cancellationToken);
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using HttpOverStream.Logging;
|
||||
|
||||
namespace HttpOverStream.NamedPipe
|
||||
{
|
||||
public class NamedPipeHttpClientBuilder
|
||||
{
|
||||
private string _pipeName;
|
||||
private ILoggerHttpOverStream _logger;
|
||||
private DelegatingHandler _outerHandler;
|
||||
private TimeSpan? _perRequestTimeout;
|
||||
private Version _httpVersion;
|
||||
|
||||
public NamedPipeHttpClientBuilder(string pipeName)
|
||||
{
|
||||
_pipeName = pipeName;
|
||||
}
|
||||
|
||||
public NamedPipeHttpClientBuilder WithLogger(ILoggerHttpOverStream logger)
|
||||
{
|
||||
_logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedPipeHttpClientBuilder WithDelegatingHandler(DelegatingHandler outerHandler)
|
||||
{
|
||||
_outerHandler = outerHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedPipeHttpClientBuilder WithPerRequestTimeout(TimeSpan perRequestTimeout)
|
||||
{
|
||||
_perRequestTimeout = perRequestTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedPipeHttpClientBuilder WithHttpVersion(Version httpVersion)
|
||||
{
|
||||
_httpVersion = httpVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClient Build()
|
||||
{
|
||||
return NamedPipeHttpClientFactory.ForPipeName(_pipeName, _logger, _perRequestTimeout, _httpVersion, _outerHandler);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,13 +7,21 @@ namespace HttpOverStream.NamedPipe
|
|||
{
|
||||
public class NamedPipeHttpClientFactory
|
||||
{
|
||||
public static HttpClient ForPipeName(string pipeName, ILoggerHttpOverStream logger = null, TimeSpan? perRequestTimeout = null, Version httpVersion = null)
|
||||
public static HttpClient ForPipeName(string pipeName, ILoggerHttpOverStream logger = null, TimeSpan? perRequestTimeout = null, Version httpVersion = null, DelegatingHandler outerHandler = null )
|
||||
{
|
||||
var httpClient = new HttpClient(new DialMessageHandler(new NamedPipeDialer(pipeName), logger, httpVersion))
|
||||
var innerHandler = new DialMessageHandler(new NamedPipeDialer(pipeName), logger, httpVersion);
|
||||
HttpClient httpClient;
|
||||
if (outerHandler != null)
|
||||
{
|
||||
BaseAddress = new Uri("http://localhost")
|
||||
};
|
||||
outerHandler.InnerHandler = innerHandler;
|
||||
httpClient = new HttpClient(outerHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpClient = new HttpClient(innerHandler);
|
||||
}
|
||||
|
||||
httpClient.BaseAddress = new Uri("http://localhost");
|
||||
if (perRequestTimeout != null)
|
||||
{
|
||||
httpClient.Timeout = perRequestTimeout.Value;
|
||||
|
|
|
@ -105,15 +105,17 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
{
|
||||
for (int i = 0; i < numberOfRequests; i++)
|
||||
{
|
||||
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName), null, httpVersion));
|
||||
client.Timeout = TimeSpan.FromSeconds(5);
|
||||
var client = new NamedPipeHttpClientBuilder(TestContext.TestName)
|
||||
.WithPerRequestTimeout(TimeSpan.FromSeconds(5))
|
||||
.WithHttpVersion(httpVersion)
|
||||
.WithDelegatingHandler(new TestLoggingHandler())
|
||||
.Build();
|
||||
var result = await client.GetAsync("http://localhost/api/e2e-tests/hello-world");
|
||||
Assert.AreEqual("Hello World", await result.Content.ReadAsAsync<string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task TestGetStressTest_ClientBeforeServer()
|
||||
{
|
||||
|
@ -140,8 +142,9 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
{
|
||||
for (int i = 0; i < numberOfRequests; i++)
|
||||
{
|
||||
var client2 = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
|
||||
client2.Timeout = TimeSpan.FromSeconds(5);
|
||||
var client2 = new NamedPipeHttpClientBuilder(TestContext.TestName)
|
||||
.WithPerRequestTimeout(TimeSpan.FromSeconds(5))
|
||||
.Build();
|
||||
var result = await client2.GetAsync("http://localhost/api/e2e-tests/hello-world");
|
||||
Assert.AreEqual("Hello World", await result.Content.ReadAsAsync<string>());
|
||||
}
|
||||
|
@ -161,8 +164,9 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
{
|
||||
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
|
||||
{
|
||||
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
|
||||
client.Timeout = TimeSpan.FromSeconds(1);
|
||||
var client = new NamedPipeHttpClientBuilder(TestContext.TestName)
|
||||
.WithPerRequestTimeout(TimeSpan.FromSeconds(1))
|
||||
.Build();
|
||||
var badContent = new StringContent("{ ", Encoding.UTF8, "application/broken");
|
||||
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", badContent);
|
||||
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
|
||||
|
@ -189,7 +193,7 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
{
|
||||
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
|
||||
{
|
||||
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
|
||||
var client = NamedPipeHttpClientFactory.ForPipeName(TestContext.TestName);
|
||||
try
|
||||
{
|
||||
var badContent = new StringContent("{ }");
|
||||
|
@ -273,7 +277,7 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
{
|
||||
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
|
||||
{
|
||||
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
|
||||
var client = NamedPipeHttpClientFactory.ForPipeName(TestContext.TestName);
|
||||
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
|
||||
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
|
||||
Assert.AreEqual("Hello Test", wlcMsg.Text);
|
||||
|
@ -283,7 +287,7 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
[TestMethod]
|
||||
public async Task TestPost_WhenNoServerListening_ThrowsTimeoutException()
|
||||
{
|
||||
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
|
||||
var client = NamedPipeHttpClientFactory.ForPipeName(TestContext.TestName);
|
||||
await Assert.ThrowsExceptionAsync<TimeoutException>(async () => await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" }));
|
||||
}
|
||||
|
||||
|
@ -334,8 +338,7 @@ namespace HttpOverStream.Server.Owin.Tests
|
|||
{
|
||||
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
|
||||
{
|
||||
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
|
||||
client.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
var client = NamedPipeHttpClientFactory.ForPipeName(TestContext.TestName, null, TimeSpan.FromMilliseconds(100));
|
||||
var sw = Stopwatch.StartNew();
|
||||
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
|
||||
{
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="TestLoggingHandler.cs" />
|
||||
<Compile Include="EndToEndTests.cs" />
|
||||
<Compile Include="OnceTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HttpOverStream.Server.Owin.Tests
|
||||
{
|
||||
public class TestLoggingHandler : DelegatingHandler
|
||||
{
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var correlationId = Guid.NewGuid();
|
||||
LogRequest(request, correlationId);
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var response = await base.SendAsync(request, cancellationToken);
|
||||
stopwatch.Stop();
|
||||
LogResponse(request, response, stopwatch.Elapsed, correlationId);
|
||||
return response;
|
||||
}
|
||||
|
||||
private void LogRequest(HttpRequestMessage request, Guid correlationId)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
Console.WriteLine("Null request");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"[{correlationId}] {request.Method?.Method} {request.RequestUri}");
|
||||
}
|
||||
|
||||
private void LogResponse(HttpRequestMessage request, HttpResponseMessage response, TimeSpan stopwatchElapsed, Guid correlationId)
|
||||
{
|
||||
Console.WriteLine($"[{correlationId}] {request?.Method?.Method} {request?.RequestUri} -> {(int)response.StatusCode} {response.StatusCode} took {(int)stopwatchElapsed.TotalMilliseconds}ms");
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче