mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 08:08:14 +08:00
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:
@ -107,6 +107,7 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
_builder.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_builder?.Dispose();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -402,11 +402,14 @@ namespace Ocelot.UnitTests.Configuration
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var handlers = new List<string> {"Polly", "Tracer"};
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("https")
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithDelegatingHandlers(handlers)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -419,6 +422,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
UpstreamPathTemplate = "/api/products/{productId}",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DelegatingHandlers = handlers
|
||||
}
|
||||
},
|
||||
}))
|
||||
@ -821,7 +825,8 @@ namespace Ocelot.UnitTests.Configuration
|
||||
result.DownstreamReRoute[0].ClaimsToClaims.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToClaims.Count);
|
||||
result.DownstreamReRoute[0].ClaimsToHeaders.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToHeaders.Count);
|
||||
result.DownstreamReRoute[0].ClaimsToQueries.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToQueries.Count);
|
||||
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
|
||||
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
|
||||
result.DownstreamReRoute[0].DelegatingHandlers.ShouldBe(expected.DownstreamReRoute[0].DelegatingHandlers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,26 +28,58 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
private readonly IConfiguration _configRoot;
|
||||
private IOcelotBuilder _ocelotBuilder;
|
||||
private readonly int _maxRetries;
|
||||
private Exception _ex;
|
||||
|
||||
public OcelotBuilderTests()
|
||||
{
|
||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
_services = new ServiceCollection();
|
||||
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
|
||||
_services.AddSingleton<IConfiguration>(_configRoot);
|
||||
_services.AddSingleton(_configRoot);
|
||||
_maxRetries = 100;
|
||||
}
|
||||
|
||||
private Exception _ex;
|
||||
[Fact]
|
||||
public void should_add_specific_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheSpecificHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_delegating_handlers_with_di()
|
||||
public void should_add_specific_delegating_handler_singleton()
|
||||
{
|
||||
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddDelegate<FakeDelegatingHandler>())
|
||||
.And(x => AddDelegate<FakeDelegatingHandlerTwo>())
|
||||
.When(x => AddSpecificDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddSpecificDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheSpecificHandlersAreSingleton())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_global_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheGlobalHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_global_delegating_handlers_singleton()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheGlobalHandlersAreSingleton())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -118,16 +150,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration()
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", "secret");
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", options);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_logger_factory()
|
||||
{
|
||||
@ -155,6 +177,62 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheSpecificHandlersAreSingleton()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var first = handlers[0];
|
||||
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var second = handlers[0];
|
||||
first.ShouldBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheSpecificHandlersAreTransient()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var first = handlers[0];
|
||||
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var second = handlers[0];
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheGlobalHandlersAreSingleton()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var first = handlers[0].DelegatingHandler;
|
||||
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var second = handlers[0].DelegatingHandler;
|
||||
first.ShouldBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheGlobalHandlersAreTransient()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var first = handlers[0].DelegatingHandler;
|
||||
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var second = handlers[0].DelegatingHandler;
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration()
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", "secret");
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", options);
|
||||
}
|
||||
|
||||
private void AddTransientGlobalDelegatingHandler<T>() where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddTransientDelegatingHandler<T>(true);
|
||||
}
|
||||
|
||||
private void AddSpecificTransientDelegatingHandler<T>() where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddTransientDelegatingHandler<T>();
|
||||
}
|
||||
|
||||
private void ThenTheCorrectAdminPathIsRegitered()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
@ -163,6 +241,14 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
|
||||
handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
@ -174,14 +260,18 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
{
|
||||
var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
|
||||
var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
|
||||
var thing = (CacheManager.Core.ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
|
||||
thing.Configuration.MaxRetries.ShouldBe(_maxRetries);
|
||||
|
||||
var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
|
||||
var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IOcelotConfiguration>));
|
||||
var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IOcelotConfiguration>));
|
||||
|
||||
var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
|
||||
var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));
|
||||
|
||||
instance.Configuration.MaxRetries.ShouldBe(_maxRetries);
|
||||
outputCache.ShouldNotBeNull();
|
||||
ocelotConfigCache.ShouldNotBeNull();
|
||||
ocelotConfigCacheManager.ShouldNotBeNull();
|
||||
fileConfigCache.ShouldNotBeNull();
|
||||
fileConfigCacheManager.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
private void WhenISetUpConsul()
|
||||
@ -208,9 +298,14 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDelegate<T>() where T : DelegatingHandler
|
||||
private void AddGlobalDelegatingHandler<T>() where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||
_ocelotBuilder.AddSingletonDelegatingHandler<T>(true);
|
||||
}
|
||||
|
||||
private void AddSpecificDelegatingHandler<T>() where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddSingletonDelegatingHandler<T>();
|
||||
}
|
||||
|
||||
private void ThenAnOcelotBuilderIsReturned()
|
||||
@ -281,6 +376,7 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
|
||||
logger.ShouldNotBeNull();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -293,6 +389,7 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
try
|
||||
{
|
||||
var tracingHandler = _serviceProvider.GetService<OcelotHttpTracingHandler>();
|
||||
tracingHandler.ShouldNotBeNull();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -19,18 +19,179 @@ namespace Ocelot.UnitTests.Requester
|
||||
public class DelegatingHandlerHandlerProviderFactoryTests
|
||||
{
|
||||
private DelegatingHandlerHandlerFactory _factory;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private DownstreamReRoute _request;
|
||||
private Response<List<Func<DelegatingHandler>>> _provider;
|
||||
private Response<List<Func<DelegatingHandler>>> _result;
|
||||
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
||||
private readonly Mock<ITracingHandlerFactory> _tracingFactory;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IServiceCollection _services;
|
||||
|
||||
public DelegatingHandlerHandlerProviderFactoryTests()
|
||||
{
|
||||
_tracingFactory = new Mock<ITracingHandlerFactory>();
|
||||
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_services = new ServiceCollection();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_follow_ordering_add_specifics()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
"FakeDelegatingHandlerTwo"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheTracingFactoryReturns())
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerThree, FakeDelegatingHandlerFour>())
|
||||
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(6))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(1))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(2))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(3))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(4))
|
||||
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(5))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_follow_ordering_order_specifics_and_globals()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandlerTwo",
|
||||
"FakeDelegatingHandler",
|
||||
"FakeDelegatingHandlerFour"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheTracingFactoryReturns())
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerFour, FakeDelegatingHandlerThree>())
|
||||
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(6))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0)) //first because global not in config
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(1)) //first from config
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(2)) //second from config
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(3)) //third from config (global)
|
||||
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(4))
|
||||
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(5))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_follow_ordering_order_specifics()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandlerTwo",
|
||||
"FakeDelegatingHandler"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheTracingFactoryReturns())
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerThree, FakeDelegatingHandlerFour>())
|
||||
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(6))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(1))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(2))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(3))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(4))
|
||||
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(5))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_follow_ordering_order_and_only_add_specifics_in_config()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheTracingFactoryReturns())
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerThree, FakeDelegatingHandlerFour>())
|
||||
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(5))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(1))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(2))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(3))
|
||||
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(4))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_follow_ordering_dont_add_specifics()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithReRouteKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheTracingFactoryReturns())
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(4))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(0))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(1))
|
||||
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(2))
|
||||
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(3))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_apply_re_route_specific()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
"FakeDelegatingHandlerTwo"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(2))
|
||||
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -41,7 +202,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
.And(x => GivenTheServiceProviderReturns<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.When(x => WhenIGet())
|
||||
.Then(x => ThenThereIsDelegatesInProvider(3))
|
||||
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
||||
@ -91,30 +252,58 @@ namespace Ocelot.UnitTests.Requester
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderReturns<TOne, TTwo>()
|
||||
private void ThenHandlerAtPositionIs<T>(int pos)
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
var delegates = _result.Data;
|
||||
var del = delegates[pos].Invoke();
|
||||
del.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void GivenTheTracingFactoryReturns()
|
||||
{
|
||||
_tracingFactory
|
||||
.Setup(x => x.Get())
|
||||
.Returns(new FakeTracingHandler());
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderReturnsGlobalDelegatingHandlers<TOne, TTwo>()
|
||||
where TOne : DelegatingHandler
|
||||
where TTwo : DelegatingHandler
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
services.AddSingleton<DelegatingHandler, TOne>();
|
||||
services.AddSingleton<DelegatingHandler, TTwo>();
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
_services.AddTransient<TOne>();
|
||||
_services.AddTransient<GlobalDelegatingHandler>(s => {
|
||||
var service = s.GetService<TOne>();
|
||||
return new GlobalDelegatingHandler(service);
|
||||
});
|
||||
_services.AddTransient<TTwo>();
|
||||
_services.AddTransient<GlobalDelegatingHandler>(s => {
|
||||
var service = s.GetService<TTwo>();
|
||||
return new GlobalDelegatingHandler(service);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderReturnsNothing()
|
||||
private void GivenTheServiceProviderReturnsSpecificDelegatingHandlers<TOne, TTwo>()
|
||||
where TOne : DelegatingHandler
|
||||
where TTwo : DelegatingHandler
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
_services.AddTransient<DelegatingHandler, TOne>();
|
||||
_services.AddTransient<DelegatingHandler, TTwo>();
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderReturnsNothing()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsReturned()
|
||||
{
|
||||
_provider.IsError.ShouldBeTrue();
|
||||
_result.IsError.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void ThenTheDelegatesAreAddedCorrectly()
|
||||
{
|
||||
var delegates = _provider.Data;
|
||||
var delegates = _result.Data;
|
||||
|
||||
var del = delegates[0].Invoke();
|
||||
var handler = (FakeDelegatingHandler) del;
|
||||
@ -134,15 +323,15 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
private void ThenItIsPolly(int i)
|
||||
{
|
||||
var delegates = _provider.Data;
|
||||
var delegates = _result.Data;
|
||||
var del = delegates[i].Invoke();
|
||||
del.ShouldBeOfType<PollyCircuitBreakingDelegatingHandler>();
|
||||
}
|
||||
|
||||
private void ThenThereIsDelegatesInProvider(int count)
|
||||
{
|
||||
_provider.ShouldNotBeNull();
|
||||
_provider.Data.Count.ShouldBe(count);
|
||||
_result.ShouldNotBeNull();
|
||||
_result.Data.Count.ShouldBe(count);
|
||||
}
|
||||
|
||||
private void GivenTheFollowingRequest(DownstreamReRoute request)
|
||||
@ -152,14 +341,19 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
private void WhenIGet()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
_factory = new DelegatingHandlerHandlerFactory(_loggerFactory.Object, _tracingFactory.Object, _qosProviderHouse.Object, _serviceProvider);
|
||||
_provider = _factory.Get(_request);
|
||||
_result = _factory.Get(_request);
|
||||
}
|
||||
|
||||
private void ThenNoDelegatesAreInTheProvider()
|
||||
{
|
||||
_provider.ShouldNotBeNull();
|
||||
_provider.Data.Count.ShouldBe(0);
|
||||
_result.ShouldNotBeNull();
|
||||
_result.Data.Count.ShouldBe(0);
|
||||
}
|
||||
}
|
||||
|
||||
internal class FakeTracingHandler : DelegatingHandler, ITracingHandler
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,42 @@ namespace Ocelot.UnitTests.Requester
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeDelegatingHandlerThree : DelegatingHandler
|
||||
{
|
||||
public FakeDelegatingHandlerThree()
|
||||
{
|
||||
Order = 3;
|
||||
}
|
||||
|
||||
public int Order { get; private set; }
|
||||
|
||||
public DateTime TimeCalled { get; private set; }
|
||||
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
TimeCalled = DateTime.Now;
|
||||
return Task.FromResult(new HttpResponseMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeDelegatingHandlerFour : DelegatingHandler
|
||||
{
|
||||
public FakeDelegatingHandlerFour()
|
||||
{
|
||||
Order = 4;
|
||||
}
|
||||
|
||||
public int Order { get; private set; }
|
||||
|
||||
public DateTime TimeCalled { get; private set; }
|
||||
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
TimeCalled = DateTime.Now;
|
||||
return Task.FromResult(new HttpResponseMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeDelegatingHandlerTwo : DelegatingHandler
|
||||
{
|
||||
public FakeDelegatingHandlerTwo()
|
||||
@ -36,12 +72,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
}
|
||||
|
||||
public int Order {get;private set;}
|
||||
|
||||
public 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 new HttpResponseMessage();
|
||||
return Task.FromResult(new HttpResponseMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user