#438 removed singleton delegating handlers as you cannot have these (#456)

This commit is contained in:
Tom Pallister 2018-07-09 08:08:39 +01:00 committed by GitHub
parent a419ed68dc
commit c8b72f31b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 643 additions and 601 deletions

View File

@ -1,79 +1,66 @@
Delegating Handers Delegating Handlers
================== ===================
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_ Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_
and I decided that it was going to be useful in various ways. Since then we extended it in `GitHub #264 <https://github.com/TomPallister/Ocelot/issues/264>`_. and I decided that it was going to be useful in various ways. Since then we extended it in `GitHub #264 <https://github.com/TomPallister/Ocelot/issues/264>`_.
Usage Usage
^^^^^ ^^^^^
In order to add delegating handlers to the HttpClient transport you need to do two main things. In order to add delegating handlers to the HttpClient transport you need to do two main things.
First in order to create a class that can be used a delegating handler it must look as follows. We are going to register these handlers in the First in order to create a class that can be used a delegating handler it must look as follows. We are going to register these handlers in the
asp.net core container so you can inject any other services you have registered into the constructor of your handler. asp.net core container so you can inject any other services you have registered into the constructor of your handler.
.. code-block:: csharp .. code-block:: csharp
public class FakeHandler : DelegatingHandler public class FakeHandler : DelegatingHandler
{ {
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{ {
//do stuff and optionally call the base handler.. //do stuff and optionally call the base handler..
return await base.SendAsync(request, cancellationToken); return await base.SendAsync(request, cancellationToken);
} }
} }
Next you must add the handlers to Ocelot's container either as singleton like follows.. Next you must add the handlers to Ocelot's container like below...
.. code-block:: csharp .. code-block:: csharp
services.AddOcelot() services.AddOcelot()
.AddSingletonDelegatingHandler<FakeHandler>() .AddDelegatingHandler<FakeHandler>()
.AddSingletonDelegatingHandler<FakeHandlerTwo>() .AddDelegatingHandler<FakeHandlerTwo>()
Or transient as below... Both of these Add methods have a default parameter called global which is set to false. If it is false then the intent of
the DelegatingHandler is to be applied to specific ReRoutes via ocelot.json (more on that later). If it is set to true
.. code-block:: csharp then it becomes a global handler and will be applied to all ReRoutes.
services.AddOcelot() e.g.
.AddTransientDelegatingHandler<FakeHandler>()
.AddTransientDelegatingHandler<FakeHandlerTwo>() As below...
Both of these Add methods have a default parameter called global which is set to false. If it is false then the intent of .. code-block:: csharp
the DelegatingHandler is to be applied to specific ReRoutes via ocelot.json (more on that later). If it is set to true
then it becomes a global handler and will be applied to all ReRoutes. services.AddOcelot()
.AddDelegatingHandler<FakeHandler>(true)
e.g.
Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers
.. code-block:: csharp then you must add the following json to the specific ReRoute in ocelot.json. The names in the array must match the class names of your
DelegatingHandlers for Ocelot to match them together.
services.AddOcelot()
.AddSingletonDelegatingHandler<FakeHandler>(true) .. code-block:: json
Or transient as below... "DelegatingHandlers": [
"FakeHandlerTwo",
.. code-block:: csharp "FakeHandler"
]
services.AddOcelot()
.AddTransientDelegatingHandler<FakeHandler>(true) You can have as many DelegatingHandlers as you want and they are run in the following order:
Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers 1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from ocelot.json.
then you must add the following json to the specific ReRoute in ocelot.json. The names in the array must match the class names of your 2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from ocelot.json ordered as they are in the DelegatingHandlers array.
DelegatingHandlers for Ocelot to match them together. 3. Tracing DelegatingHandler if enabled (see tracing docs).
4. QoS DelegatingHandler if enabled (see QoS docs).
.. code-block:: json 5. The HttpClient sends the HttpRequestMessage.
"DelegatingHandlers": [ Hopefully other people will find this feature useful!
"FakeHandlerTwo",
"FakeHandler"
]
You can have as many DelegatingHandlers as you want and they are run in the following order:
1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from ocelot.json.
2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from ocelot.json ordered as they are in the DelegatingHandlers array.
3. Tracing DelegatingHandler if enabled (see tracing docs).
4. QoS DelegatingHandler if enabled (see QoS docs).
5. The HttpClient sends the HttpRequestMessage.
Hopefully other people will find this feature useful!

View File

@ -1,6 +1,6 @@
{ {
"projects": [ "src", "test" ], "projects": [ "src", "test" ],
"sdk": { "sdk": {
"version": "2.1.300" "version": "2.1.301"
} }
} }

View File

@ -19,10 +19,7 @@ namespace Ocelot.DependencyInjection
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions); IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
IOcelotBuilder AddSingletonDelegatingHandler<T>(bool global = false) IOcelotBuilder AddDelegatingHandler<T>(bool global = false)
where T : DelegatingHandler;
IOcelotBuilder AddTransientDelegatingHandler<T>(bool global = false)
where T : DelegatingHandler; where T : DelegatingHandler;
IOcelotBuilder AddSingletonDefinedAggregator<T>() IOcelotBuilder AddSingletonDefinedAggregator<T>()

View File

@ -212,26 +212,7 @@ namespace Ocelot.DependencyInjection
return this; return this;
} }
public IOcelotBuilder AddSingletonDelegatingHandler<THandler>(bool global = false) public IOcelotBuilder AddDelegatingHandler<THandler>(bool global = false)
where THandler : DelegatingHandler
{
if(global)
{
_services.AddSingleton<THandler>();
_services.AddSingleton<GlobalDelegatingHandler>(s => {
var service = s.GetService<THandler>();
return new GlobalDelegatingHandler(service);
});
}
else
{
_services.AddSingleton<DelegatingHandler, THandler>();
}
return this;
}
public IOcelotBuilder AddTransientDelegatingHandler<THandler>(bool global = false)
where THandler : DelegatingHandler where THandler : DelegatingHandler
{ {
if(global) if(global)

View File

@ -101,6 +101,57 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_call_global_di_handlers_multiple_times()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 9187,
}
},
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:9187", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningWithGlobalHandlerRegisteredInDi<FakeHandlerAgain>())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
[Fact] [Fact]
public void should_call_global_di_handlers_with_dependency() public void should_call_global_di_handlers_with_dependency()
{ {
@ -198,6 +249,17 @@ namespace Ocelot.AcceptanceTests
return base.SendAsync(request, cancellationToken); return base.SendAsync(request, cancellationToken);
} }
} }
// ReSharper disable once ClassNeverInstantiated.Local
private class FakeHandlerAgain : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Console.WriteLine(request.RequestUri);
//do stuff and optionally call the base handler..
return await base.SendAsync(request, cancellationToken);
}
}
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody) private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody)
{ {

View File

@ -237,8 +237,8 @@ namespace Ocelot.AcceptanceTests
{ {
s.AddSingleton(_webHostBuilder); s.AddSingleton(_webHostBuilder);
s.AddOcelot() s.AddOcelot()
.AddSingletonDelegatingHandler<TOne>() .AddDelegatingHandler<TOne>()
.AddSingletonDelegatingHandler<TWo>(); .AddDelegatingHandler<TWo>();
}) })
.Configure(a => .Configure(a =>
{ {
@ -303,8 +303,39 @@ namespace Ocelot.AcceptanceTests
{ {
s.AddSingleton(_webHostBuilder); s.AddSingleton(_webHostBuilder);
s.AddOcelot() s.AddOcelot()
.AddSingletonDelegatingHandler<TOne>(true) .AddDelegatingHandler<TOne>(true)
.AddSingletonDelegatingHandler<TWo>(true); .AddDelegatingHandler<TWo>(true);
})
.Configure(a =>
{
a.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningWithGlobalHandlerRegisteredInDi<TOne>()
where TOne : 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("ocelot.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddSingleton(_webHostBuilder);
s.AddOcelot()
.AddDelegatingHandler<TOne>(true);
}) })
.Configure(a => .Configure(a =>
{ {
@ -336,7 +367,7 @@ namespace Ocelot.AcceptanceTests
s.AddSingleton(_webHostBuilder); s.AddSingleton(_webHostBuilder);
s.AddSingleton<FakeDependency>(dependency); s.AddSingleton<FakeDependency>(dependency);
s.AddOcelot() s.AddOcelot()
.AddSingletonDelegatingHandler<TOne>(true); .AddDelegatingHandler<TOne>(true);
}) })
.Configure(a => .Configure(a =>
{ {

View File

@ -9,6 +9,9 @@
using Ocelot.Middleware; using Ocelot.Middleware;
using System; using System;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using System.Net.Http;
using System.Threading.Tasks;
using System.Threading;
public class Program public class Program
{ {
@ -35,10 +38,11 @@
}); });
s.AddOcelot() s.AddOcelot()
.AddCacheManager(x => .AddDelegatingHandler<FakeHandler>(true)
{ // .AddCacheManager(x =>
x.WithDictionaryHandle(); // {
}) // x.WithDictionaryHandle();
// })
/*.AddOpenTracing(option => /*.AddOpenTracing(option =>
{ {
option.CollectorUrl = "http://localhost:9618"; option.CollectorUrl = "http://localhost:9618";
@ -60,4 +64,15 @@
.Run(); .Run();
} }
} }
public class FakeHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Console.WriteLine(request.RequestUri);
//do stuff and optionally call the base handler..
return await base.SendAsync(request, cancellationToken);
}
}
} }

View File

@ -1,483 +1,452 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using CacheManager.Core; using CacheManager.Core;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Internal; using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ocelot.Cache; using Ocelot.Cache;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Configuration.Setter; using Ocelot.Configuration.Setter;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
using Ocelot.Requester; using Ocelot.Requester;
using Ocelot.UnitTests.Requester; using Ocelot.UnitTests.Requester;
using Shouldly; using Shouldly;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using static Ocelot.UnitTests.Middleware.UserDefinedResponseAggregatorTests; using static Ocelot.UnitTests.Middleware.UserDefinedResponseAggregatorTests;
using Ocelot.Middleware.Multiplexer; using Ocelot.Middleware.Multiplexer;
namespace Ocelot.UnitTests.DependencyInjection namespace Ocelot.UnitTests.DependencyInjection
{ {
public class OcelotBuilderTests public class OcelotBuilderTests
{ {
private readonly IServiceCollection _services; private readonly IServiceCollection _services;
private IServiceProvider _serviceProvider; private IServiceProvider _serviceProvider;
private readonly IConfiguration _configRoot; private readonly IConfiguration _configRoot;
private IOcelotBuilder _ocelotBuilder; private IOcelotBuilder _ocelotBuilder;
private readonly int _maxRetries; private readonly int _maxRetries;
private Exception _ex; private Exception _ex;
public OcelotBuilderTests() public OcelotBuilderTests()
{ {
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>()); _configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
_services = new ServiceCollection(); _services = new ServiceCollection();
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>(); _services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
_services.AddSingleton(_configRoot); _services.AddSingleton(_configRoot);
_maxRetries = 100; _maxRetries = 100;
} }
[Fact] [Fact]
public void should_add_specific_delegating_handlers_transient() public void should_add_specific_delegating_handlers_transient()
{ {
this.Given(x => WhenISetUpOcelotServices()) this.Given(x => WhenISetUpOcelotServices())
.When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>()) .When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
.And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>()) .And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>()) .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
.And(x => ThenTheSpecificHandlersAreTransient()) .And(x => ThenTheSpecificHandlersAreTransient())
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_add_specific_delegating_handler_singleton() public void should_add_global_delegating_handlers_transient()
{ {
this.Given(x => WhenISetUpOcelotServices()) this.Given(x => WhenISetUpOcelotServices())
.When(x => AddSpecificDelegatingHandler<FakeDelegatingHandler>()) .When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
.And(x => AddSpecificDelegatingHandler<FakeDelegatingHandlerTwo>()) .And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>()) .Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
.And(x => ThenTheSpecificHandlersAreSingleton()) .And(x => ThenTheGlobalHandlersAreTransient())
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_add_global_delegating_handlers_transient() public void should_set_up_services()
{ {
this.Given(x => WhenISetUpOcelotServices()) this.When(x => WhenISetUpOcelotServices())
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>()) .Then(x => ThenAnExceptionIsntThrown())
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>()) .BDDfy();
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>()) }
.And(x => ThenTheGlobalHandlersAreTransient())
.BDDfy(); [Fact]
} public void should_return_ocelot_builder()
{
[Fact] this.When(x => WhenISetUpOcelotServices())
public void should_add_global_delegating_handlers_singleton() .Then(x => ThenAnOcelotBuilderIsReturned())
{ .BDDfy();
this.Given(x => WhenISetUpOcelotServices()) }
.When(x => AddGlobalDelegatingHandler<FakeDelegatingHandler>())
.And(x => AddGlobalDelegatingHandler<FakeDelegatingHandlerTwo>()) [Fact]
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>()) public void should_set_up_cache_manager()
.And(x => ThenTheGlobalHandlersAreSingleton()) {
.BDDfy(); this.Given(x => WhenISetUpOcelotServices())
} .When(x => WhenISetUpCacheManager())
.Then(x => ThenAnExceptionIsntThrown())
[Fact] .And(x => OnlyOneVersionOfEachCacheIsRegistered())
public void should_set_up_services() .BDDfy();
{ }
this.When(x => WhenISetUpOcelotServices())
.Then(x => ThenAnExceptionIsntThrown()) [Fact]
.BDDfy(); public void should_set_up_consul()
} {
this.Given(x => WhenISetUpOcelotServices())
[Fact] .When(x => WhenISetUpConsul())
public void should_return_ocelot_builder() .Then(x => ThenAnExceptionIsntThrown())
{ .BDDfy();
this.When(x => WhenISetUpOcelotServices()) }
.Then(x => ThenAnOcelotBuilderIsReturned())
.BDDfy(); [Fact]
} public void should_set_up_rafty()
{
[Fact] this.Given(x => WhenISetUpOcelotServices())
public void should_set_up_cache_manager() .When(x => WhenISetUpRafty())
{ .Then(x => ThenAnExceptionIsntThrown())
this.Given(x => WhenISetUpOcelotServices()) .Then(x => ThenTheCorrectAdminPathIsRegitered())
.When(x => WhenISetUpCacheManager()) .BDDfy();
.Then(x => ThenAnExceptionIsntThrown()) }
.And(x => OnlyOneVersionOfEachCacheIsRegistered())
.BDDfy(); [Fact]
} public void should_set_up_administration_with_identity_server_options()
{
[Fact] Action<IdentityServerAuthenticationOptions> options = o => {};
public void should_set_up_consul()
{ this.Given(x => WhenISetUpOcelotServices())
this.Given(x => WhenISetUpOcelotServices()) .When(x => WhenISetUpAdministration(options))
.When(x => WhenISetUpConsul()) .Then(x => ThenAnExceptionIsntThrown())
.Then(x => ThenAnExceptionIsntThrown()) .Then(x => ThenTheCorrectAdminPathIsRegitered())
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_set_up_rafty() public void should_set_up_administration()
{ {
this.Given(x => WhenISetUpOcelotServices()) this.Given(x => WhenISetUpOcelotServices())
.When(x => WhenISetUpRafty()) .When(x => WhenISetUpAdministration())
.Then(x => ThenAnExceptionIsntThrown()) .Then(x => ThenAnExceptionIsntThrown())
.Then(x => ThenTheCorrectAdminPathIsRegitered()) .Then(x => ThenTheCorrectAdminPathIsRegitered())
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_set_up_administration_with_identity_server_options() public void should_use_logger_factory()
{ {
Action<IdentityServerAuthenticationOptions> options = o => {}; this.Given(x => WhenISetUpOcelotServices())
.When(x => WhenIValidateScopes())
this.Given(x => WhenISetUpOcelotServices()) .When(x => WhenIAccessLoggerFactory())
.When(x => WhenISetUpAdministration(options)) .Then(x => ThenAnExceptionIsntThrown())
.Then(x => ThenAnExceptionIsntThrown()) .BDDfy();
.Then(x => ThenTheCorrectAdminPathIsRegitered()) }
.BDDfy();
} [Fact]
public void should_set_up_tracing()
[Fact] {
public void should_set_up_administration() this.Given(x => WhenISetUpOcelotServices())
{ .When(x => WhenISetUpOpentracing())
this.Given(x => WhenISetUpOcelotServices()) .When(x => WhenIAccessOcelotHttpTracingHandler())
.When(x => WhenISetUpAdministration()) .BDDfy();
.Then(x => ThenAnExceptionIsntThrown()) }
.Then(x => ThenTheCorrectAdminPathIsRegitered())
.BDDfy(); [Fact]
} public void should_set_up_without_passing_in_config()
{
[Fact] this.When(x => WhenISetUpOcelotServicesWithoutConfig())
public void should_use_logger_factory() .Then(x => ThenAnExceptionIsntThrown())
{ .BDDfy();
this.Given(x => WhenISetUpOcelotServices()) }
.When(x => WhenIValidateScopes())
.When(x => WhenIAccessLoggerFactory()) [Fact]
.Then(x => ThenAnExceptionIsntThrown()) public void should_add_singleton_defined_aggregators()
.BDDfy(); {
} this.Given(x => WhenISetUpOcelotServices())
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
[Fact] .When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
public void should_set_up_tracing() .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
{ .And(x => ThenTheAggregatorsAreSingleton<TestDefinedAggregator, TestDefinedAggregator>())
this.Given(x => WhenISetUpOcelotServices()) .BDDfy();
.When(x => WhenISetUpOpentracing()) }
.When(x => WhenIAccessOcelotHttpTracingHandler())
.BDDfy(); [Fact]
} public void should_add_transient_defined_aggregators()
{
[Fact] this.Given(x => WhenISetUpOcelotServices())
public void should_set_up_without_passing_in_config() .When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
{ .When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
this.When(x => WhenISetUpOcelotServicesWithoutConfig()) .Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
.Then(x => ThenAnExceptionIsntThrown()) .And(x => ThenTheAggregatorsAreTransient<TestDefinedAggregator, TestDefinedAggregator>())
.BDDfy(); .BDDfy();
} }
[Fact] private void AddSingletonDefinedAggregator<T>()
public void should_add_singleton_defined_aggregators() where T : class, IDefinedAggregator
{ {
this.Given(x => WhenISetUpOcelotServices()) _ocelotBuilder.AddSingletonDefinedAggregator<T>();
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>()) }
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>()) private void AddTransientDefinedAggregator<T>()
.And(x => ThenTheAggregatorsAreSingleton<TestDefinedAggregator, TestDefinedAggregator>()) where T : class, IDefinedAggregator
.BDDfy(); {
} _ocelotBuilder.AddTransientDefinedAggregator<T>();
}
[Fact]
public void should_add_transient_defined_aggregators() private void ThenTheSpecificHandlersAreSingleton()
{ {
this.Given(x => WhenISetUpOcelotServices()) var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
.When(x => AddTransientDefinedAggregator<TestDefinedAggregator>()) var first = handlers[0];
.When(x => AddTransientDefinedAggregator<TestDefinedAggregator>()) handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>()) var second = handlers[0];
.And(x => ThenTheAggregatorsAreTransient<TestDefinedAggregator, TestDefinedAggregator>()) first.ShouldBe(second);
.BDDfy(); }
}
private void ThenTheSpecificHandlersAreTransient()
private void AddSingletonDefinedAggregator<T>() {
where T : class, IDefinedAggregator var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
{ var first = handlers[0];
_ocelotBuilder.AddSingletonDefinedAggregator<T>(); handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
} var second = handlers[0];
first.ShouldNotBe(second);
private void AddTransientDefinedAggregator<T>() }
where T : class, IDefinedAggregator
{ private void ThenTheGlobalHandlersAreTransient()
_ocelotBuilder.AddTransientDefinedAggregator<T>(); {
} var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
var first = handlers[0].DelegatingHandler;
private void ThenTheSpecificHandlersAreSingleton() handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
{ var second = handlers[0].DelegatingHandler;
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList(); first.ShouldNotBe(second);
var first = handlers[0]; }
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
var second = handlers[0]; private void WhenISetUpAdministration()
first.ShouldBe(second); {
} _ocelotBuilder.AddAdministration("/administration", "secret");
}
private void ThenTheSpecificHandlersAreTransient()
{ private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList(); {
var first = handlers[0]; _ocelotBuilder.AddAdministration("/administration", options);
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList(); }
var second = handlers[0];
first.ShouldNotBe(second); private void AddTransientGlobalDelegatingHandler<T>()
} where T : DelegatingHandler
{
private void ThenTheGlobalHandlersAreSingleton() _ocelotBuilder.AddDelegatingHandler<T>(true);
{ }
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
var first = handlers[0].DelegatingHandler; private void AddSpecificTransientDelegatingHandler<T>()
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList(); where T : DelegatingHandler
var second = handlers[0].DelegatingHandler; {
first.ShouldBe(second); _ocelotBuilder.AddDelegatingHandler<T>();
} }
private void ThenTheGlobalHandlersAreTransient() private void ThenTheCorrectAdminPathIsRegitered()
{ {
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList(); _serviceProvider = _services.BuildServiceProvider();
var first = handlers[0].DelegatingHandler; var path = _serviceProvider.GetService<IAdministrationPath>();
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList(); path.Path.ShouldBe("/administration");
var second = handlers[0].DelegatingHandler; }
first.ShouldNotBe(second);
} private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
{
private void WhenISetUpAdministration() _serviceProvider = _services.BuildServiceProvider();
{ var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
_ocelotBuilder.AddAdministration("/administration", "secret"); handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
} handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
}
private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
{ private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
_ocelotBuilder.AddAdministration("/administration", options); {
} _serviceProvider = _services.BuildServiceProvider();
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
private void AddTransientGlobalDelegatingHandler<T>() handlers[0].ShouldBeOfType<TOne>();
where T : DelegatingHandler handlers[1].ShouldBeOfType<TWo>();
{ }
_ocelotBuilder.AddTransientDelegatingHandler<T>(true);
} private void ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TOne, TWo>()
{
private void AddSpecificTransientDelegatingHandler<T>() _serviceProvider = _services.BuildServiceProvider();
where T : DelegatingHandler var handlers = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
{ handlers[0].ShouldBeOfType<TOne>();
_ocelotBuilder.AddTransientDelegatingHandler<T>(); handlers[1].ShouldBeOfType<TWo>();
} }
private void ThenTheCorrectAdminPathIsRegitered() private void ThenTheAggregatorsAreTransient<TOne, TWo>()
{ {
_serviceProvider = _services.BuildServiceProvider(); var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
var path = _serviceProvider.GetService<IAdministrationPath>(); var first = aggregators[0];
path.Path.ShouldBe("/administration"); aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
} var second = aggregators[0];
first.ShouldNotBe(second);
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>() }
{
_serviceProvider = _services.BuildServiceProvider(); private void ThenTheAggregatorsAreSingleton<TOne, TWo>()
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList(); {
handlers[0].DelegatingHandler.ShouldBeOfType<TOne>(); var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
handlers[1].DelegatingHandler.ShouldBeOfType<TWo>(); var first = aggregators[0];
} aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
var second = aggregators[0];
private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>() first.ShouldBe(second);
{ }
_serviceProvider = _services.BuildServiceProvider();
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList(); private void OnlyOneVersionOfEachCacheIsRegistered()
handlers[0].ShouldBeOfType<TOne>(); {
handlers[1].ShouldBeOfType<TWo>(); var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
} var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
private void ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TOne, TWo>() var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IInternalConfiguration>));
{ var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IInternalConfiguration>));
_serviceProvider = _services.BuildServiceProvider(); var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
var handlers = _serviceProvider.GetServices<IDefinedAggregator>().ToList(); var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));
handlers[0].ShouldBeOfType<TOne>();
handlers[1].ShouldBeOfType<TWo>(); instance.Configuration.MaxRetries.ShouldBe(_maxRetries);
} outputCache.ShouldNotBeNull();
ocelotConfigCache.ShouldNotBeNull();
private void ThenTheAggregatorsAreTransient<TOne, TWo>() ocelotConfigCacheManager.ShouldNotBeNull();
{ fileConfigCache.ShouldNotBeNull();
var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList(); fileConfigCacheManager.ShouldNotBeNull();
var first = aggregators[0]; }
aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
var second = aggregators[0]; private void WhenISetUpConsul()
first.ShouldNotBe(second); {
} try
{
private void ThenTheAggregatorsAreSingleton<TOne, TWo>() _ocelotBuilder.AddStoreOcelotConfigurationInConsul();
{ }
var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList(); catch (Exception e)
var first = aggregators[0]; {
aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList(); _ex = e;
var second = aggregators[0]; }
first.ShouldBe(second); }
}
private void WhenISetUpRafty()
private void OnlyOneVersionOfEachCacheIsRegistered() {
{ try
var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>)); {
var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>)); _ocelotBuilder.AddAdministration("/administration", "secret").AddRafty();
var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance; }
var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IInternalConfiguration>)); catch (Exception e)
var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IInternalConfiguration>)); {
var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>)); _ex = e;
var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>)); }
}
instance.Configuration.MaxRetries.ShouldBe(_maxRetries);
outputCache.ShouldNotBeNull(); private void AddGlobalDelegatingHandler<T>()
ocelotConfigCache.ShouldNotBeNull(); where T : DelegatingHandler
ocelotConfigCacheManager.ShouldNotBeNull(); {
fileConfigCache.ShouldNotBeNull(); _ocelotBuilder.AddDelegatingHandler<T>(true);
fileConfigCacheManager.ShouldNotBeNull(); }
}
private void AddSpecificDelegatingHandler<T>()
private void WhenISetUpConsul() where T : DelegatingHandler
{ {
try _ocelotBuilder.AddDelegatingHandler<T>();
{ }
_ocelotBuilder.AddStoreOcelotConfigurationInConsul();
} private void ThenAnOcelotBuilderIsReturned()
catch (Exception e) {
{ _ocelotBuilder.ShouldBeOfType<OcelotBuilder>();
_ex = e; }
}
} private void WhenISetUpOcelotServices()
{
private void WhenISetUpRafty() try
{ {
try _ocelotBuilder = _services.AddOcelot(_configRoot);
{ }
_ocelotBuilder.AddAdministration("/administration", "secret").AddRafty(); catch (Exception e)
} {
catch (Exception e) _ex = e;
{ }
_ex = e; }
}
} private void WhenISetUpOcelotServicesWithoutConfig()
{
private void AddGlobalDelegatingHandler<T>() try
where T : DelegatingHandler {
{ _ocelotBuilder = _services.AddOcelot();
_ocelotBuilder.AddSingletonDelegatingHandler<T>(true); }
} catch (Exception e)
{
private void AddSpecificDelegatingHandler<T>() _ex = e;
where T : DelegatingHandler }
{ }
_ocelotBuilder.AddSingletonDelegatingHandler<T>();
} private void WhenISetUpCacheManager()
{
private void ThenAnOcelotBuilderIsReturned() try
{ {
_ocelotBuilder.ShouldBeOfType<OcelotBuilder>(); _ocelotBuilder.AddCacheManager(x => {
} x.WithMaxRetries(_maxRetries);
x.WithDictionaryHandle();
private void WhenISetUpOcelotServices() });
{ }
try catch (Exception e)
{ {
_ocelotBuilder = _services.AddOcelot(_configRoot); _ex = e;
} }
catch (Exception e) }
{
_ex = e; private void WhenISetUpOpentracing()
} {
} try
{
private void WhenISetUpOcelotServicesWithoutConfig() _ocelotBuilder.AddOpenTracing(
{ option =>
try {
{ option.CollectorUrl = "http://localhost:9618";
_ocelotBuilder = _services.AddOcelot(); option.Service = "Ocelot.ManualTest";
} }
catch (Exception e) );
{ }
_ex = e; catch (Exception e)
} {
} _ex = e;
}
private void WhenISetUpCacheManager() }
{
try private void WhenIAccessLoggerFactory()
{ {
_ocelotBuilder.AddCacheManager(x => { try
x.WithMaxRetries(_maxRetries); {
x.WithDictionaryHandle(); _serviceProvider = _services.BuildServiceProvider();
}); var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
} logger.ShouldNotBeNull();
catch (Exception e) }
{ catch (Exception e)
_ex = e; {
} _ex = e;
} }
}
private void WhenISetUpOpentracing()
{ private void WhenIAccessOcelotHttpTracingHandler()
try {
{ try
_ocelotBuilder.AddOpenTracing( {
option => var tracingHandler = _serviceProvider.GetService<OcelotHttpTracingHandler>();
{ tracingHandler.ShouldNotBeNull();
option.CollectorUrl = "http://localhost:9618"; }
option.Service = "Ocelot.ManualTest"; catch (Exception e)
} {
); _ex = e;
} }
catch (Exception e) }
{
_ex = e; private void WhenIValidateScopes()
} {
} try
{
private void WhenIAccessLoggerFactory() _serviceProvider = _services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });
{ }
try catch (Exception e)
{ {
_serviceProvider = _services.BuildServiceProvider(); _ex = e;
var logger = _serviceProvider.GetService<IFileConfigurationSetter>(); }
logger.ShouldNotBeNull(); }
}
catch (Exception e) private void ThenAnExceptionIsntThrown()
{ {
_ex = e; _ex.ShouldBeNull();
} }
} }
}
private void WhenIAccessOcelotHttpTracingHandler()
{
try
{
var tracingHandler = _serviceProvider.GetService<OcelotHttpTracingHandler>();
tracingHandler.ShouldNotBeNull();
}
catch (Exception e)
{
_ex = e;
}
}
private void WhenIValidateScopes()
{
try
{
_serviceProvider = _services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });
}
catch (Exception e)
{
_ex = e;
}
}
private void ThenAnExceptionIsntThrown()
{
_ex.ShouldBeNull();
}
}
}