Feature/re route specific handlers (#269)

* #264 added handlers to config

* #264 added global handlers object and defaut param for method, not sure this is correct api for users yet

* #264 Can now add all sorts of delegating handlers in all sorts of ways

* +semver: breaking #264
This commit is contained in:
Tom Pallister
2018-03-10 21:02:59 +00:00
committed by GitHub
parent a31a3ae0fc
commit 4c840d40a6
24 changed files with 692 additions and 137 deletions

View File

@ -107,6 +107,7 @@ namespace Ocelot.AcceptanceTests
_builder.Start();
}
public void Dispose()
{
_builder?.Dispose();

View File

@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;

View File

@ -26,9 +26,48 @@ namespace Ocelot.AcceptanceTests
_steps = new Steps();
}
[Fact]
public void should_call_re_route_ordered_specific_handlers()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 7197,
}
},
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
DelegatingHandlers = new List<string>
{
"FakeHandlerTwo",
"FakeHandler"
}
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7197", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningWithSpecficHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => ThenTheOrderedHandlersAreCalledCorrectly())
.BDDfy();
}
[Fact]
public void should_call_di_handlers()
public void should_call_global_di_handlers()
{
var configuration = new FileConfiguration
{
@ -54,7 +93,7 @@ namespace Ocelot.AcceptanceTests
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7187", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningWithHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
.And(x => _steps.GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
@ -62,9 +101,8 @@ namespace Ocelot.AcceptanceTests
.BDDfy();
}
[Fact]
public void should_call_di_handlers_with_dependency()
public void should_call_global_di_handlers_with_dependency()
{
var configuration = new FileConfiguration
{
@ -92,7 +130,7 @@ namespace Ocelot.AcceptanceTests
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7188", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningWithHandlersRegisteredInDi<FakeHandlerWithDependency>(dependency))
.And(x => _steps.GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<FakeHandlerWithDependency>(dependency))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
@ -110,45 +148,54 @@ namespace Ocelot.AcceptanceTests
FakeHandler.TimeCalled.ShouldBeLessThan(FakeHandlerTwo.TimeCalled);
}
private void ThenTheOrderedHandlersAreCalledCorrectly()
{
FakeHandlerTwo.TimeCalled.ShouldBeLessThan(FakeHandler.TimeCalled);
}
public class FakeDependency
{
public bool Called;
}
class FakeHandlerWithDependency : DelegatingHandler
// ReSharper disable once ClassNeverInstantiated.Local
private class FakeHandlerWithDependency : DelegatingHandler
{
private FakeDependency _dependency;
private readonly FakeDependency _dependency;
public FakeHandlerWithDependency(FakeDependency dependency)
{
_dependency = dependency;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
_dependency.Called = true;
return await base.SendAsync(request, cancellationToken);
return base.SendAsync(request, cancellationToken);
}
}
class FakeHandler : DelegatingHandler
// ReSharper disable once ClassNeverInstantiated.Local
private class FakeHandler : DelegatingHandler
{
public static DateTime TimeCalled { get; private set; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
TimeCalled = DateTime.Now;
return await base.SendAsync(request, cancellationToken);
return base.SendAsync(request, cancellationToken);
}
}
class FakeHandlerTwo : DelegatingHandler
// ReSharper disable once ClassNeverInstantiated.Local
private class FakeHandlerTwo : DelegatingHandler
{
public static DateTime TimeCalled { get; private set; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
TimeCalled = DateTime.Now;
return await base.SendAsync(request, cancellationToken);
return base.SendAsync(request, cancellationToken);
}
}

View File

@ -50,4 +50,9 @@
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
</ItemGroup>
<ItemGroup>
<Reference Include="Castle.Core">
<HintPath>..\..\..\..\Users\TGP\.nuget\packages\castle.core\4.2.1\lib\netstandard1.3\Castle.Core.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -25,6 +25,7 @@ using Ocelot.AcceptanceTests.Caching;
using System.IO.Compression;
using System.Text;
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
using Ocelot.Requester;
namespace Ocelot.AcceptanceTests
{
@ -175,7 +176,7 @@ namespace Ocelot.AcceptanceTests
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne, TWo>()
public void GivenOcelotIsRunningWithSpecficHandlersRegisteredInDi<TOne, TWo>()
where TOne : DelegatingHandler
where TWo : DelegatingHandler
{
@ -195,8 +196,8 @@ namespace Ocelot.AcceptanceTests
{
s.AddSingleton(_webHostBuilder);
s.AddOcelot()
.AddDelegatingHandler<TOne>()
.AddDelegatingHandler<TWo>();
.AddSingletonDelegatingHandler<TOne>()
.AddSingletonDelegatingHandler<TWo>();
})
.Configure(a =>
{
@ -208,7 +209,40 @@ namespace Ocelot.AcceptanceTests
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne>(FakeDependency dependency)
public void GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<TOne, TWo>()
where TOne : DelegatingHandler
where TWo : DelegatingHandler
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddSingleton(_webHostBuilder);
s.AddOcelot()
.AddSingletonDelegatingHandler<TOne>(true)
.AddSingletonDelegatingHandler<TWo>(true);
})
.Configure(a =>
{
a.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<TOne>(FakeDependency dependency)
where TOne : DelegatingHandler
{
_webHostBuilder = new WebHostBuilder();
@ -228,7 +262,7 @@ namespace Ocelot.AcceptanceTests
s.AddSingleton(_webHostBuilder);
s.AddSingleton<FakeDependency>(dependency);
s.AddOcelot()
.AddDelegatingHandler<TOne>();
.AddSingletonDelegatingHandler<TOne>(true);
})
.Configure(a =>
{
@ -618,15 +652,16 @@ namespace Ocelot.AcceptanceTests
public void GivenThePostHasGzipContent(object input)
{
string json = JsonConvert.SerializeObject(input);
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
MemoryStream ms = new MemoryStream();
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
var json = JsonConvert.SerializeObject(input);
var jsonBytes = Encoding.UTF8.GetBytes(json);
var ms = new MemoryStream();
using (var gzip = new GZipStream(ms, CompressionMode.Compress, true))
{
gzip.Write(jsonBytes, 0, jsonBytes.Length);
}
ms.Position = 0;
StreamContent content = new StreamContent(ms);
var content = new StreamContent(ms);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentEncoding.Add("gzip");
_postContent = content;