mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-23 00:32:50 +08:00
This commit is contained in:
parent
a419ed68dc
commit
c8b72f31b5
@ -1,5 +1,5 @@
|
||||
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>`_
|
||||
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>`_.
|
||||
@ -23,21 +23,13 @@ asp.net core container so you can inject any other services you have registered
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
services.AddOcelot()
|
||||
.AddSingletonDelegatingHandler<FakeHandler>()
|
||||
.AddSingletonDelegatingHandler<FakeHandlerTwo>()
|
||||
|
||||
Or transient as below...
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
services.AddOcelot()
|
||||
.AddTransientDelegatingHandler<FakeHandler>()
|
||||
.AddTransientDelegatingHandler<FakeHandlerTwo>()
|
||||
.AddDelegatingHandler<FakeHandler>()
|
||||
.AddDelegatingHandler<FakeHandlerTwo>()
|
||||
|
||||
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
|
||||
@ -45,17 +37,12 @@ then it becomes a global handler and will be applied to all ReRoutes.
|
||||
|
||||
e.g.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
services.AddOcelot()
|
||||
.AddSingletonDelegatingHandler<FakeHandler>(true)
|
||||
|
||||
Or transient as below...
|
||||
As below...
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
services.AddOcelot()
|
||||
.AddTransientDelegatingHandler<FakeHandler>(true)
|
||||
.AddDelegatingHandler<FakeHandler>(true)
|
||||
|
||||
Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers
|
||||
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
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"projects": [ "src", "test" ],
|
||||
"sdk": {
|
||||
"version": "2.1.300"
|
||||
"version": "2.1.301"
|
||||
}
|
||||
}
|
@ -19,10 +19,7 @@ namespace Ocelot.DependencyInjection
|
||||
|
||||
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
||||
|
||||
IOcelotBuilder AddSingletonDelegatingHandler<T>(bool global = false)
|
||||
where T : DelegatingHandler;
|
||||
|
||||
IOcelotBuilder AddTransientDelegatingHandler<T>(bool global = false)
|
||||
IOcelotBuilder AddDelegatingHandler<T>(bool global = false)
|
||||
where T : DelegatingHandler;
|
||||
|
||||
IOcelotBuilder AddSingletonDefinedAggregator<T>()
|
||||
|
@ -212,26 +212,7 @@ namespace Ocelot.DependencyInjection
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddSingletonDelegatingHandler<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)
|
||||
public IOcelotBuilder AddDelegatingHandler<THandler>(bool global = false)
|
||||
where THandler : DelegatingHandler
|
||||
{
|
||||
if(global)
|
||||
|
@ -101,6 +101,57 @@ namespace Ocelot.AcceptanceTests
|
||||
.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]
|
||||
public void should_call_global_di_handlers_with_dependency()
|
||||
{
|
||||
@ -198,6 +249,17 @@ namespace Ocelot.AcceptanceTests
|
||||
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)
|
||||
{
|
||||
|
@ -237,8 +237,8 @@ namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
s.AddSingleton(_webHostBuilder);
|
||||
s.AddOcelot()
|
||||
.AddSingletonDelegatingHandler<TOne>()
|
||||
.AddSingletonDelegatingHandler<TWo>();
|
||||
.AddDelegatingHandler<TOne>()
|
||||
.AddDelegatingHandler<TWo>();
|
||||
})
|
||||
.Configure(a =>
|
||||
{
|
||||
@ -303,8 +303,39 @@ namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
s.AddSingleton(_webHostBuilder);
|
||||
s.AddOcelot()
|
||||
.AddSingletonDelegatingHandler<TOne>(true)
|
||||
.AddSingletonDelegatingHandler<TWo>(true);
|
||||
.AddDelegatingHandler<TOne>(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 =>
|
||||
{
|
||||
@ -336,7 +367,7 @@ namespace Ocelot.AcceptanceTests
|
||||
s.AddSingleton(_webHostBuilder);
|
||||
s.AddSingleton<FakeDependency>(dependency);
|
||||
s.AddOcelot()
|
||||
.AddSingletonDelegatingHandler<TOne>(true);
|
||||
.AddDelegatingHandler<TOne>(true);
|
||||
})
|
||||
.Configure(a =>
|
||||
{
|
||||
|
@ -9,6 +9,9 @@
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
|
||||
public class Program
|
||||
{
|
||||
@ -35,10 +38,11 @@
|
||||
});
|
||||
|
||||
s.AddOcelot()
|
||||
.AddCacheManager(x =>
|
||||
{
|
||||
x.WithDictionaryHandle();
|
||||
})
|
||||
.AddDelegatingHandler<FakeHandler>(true)
|
||||
// .AddCacheManager(x =>
|
||||
// {
|
||||
// x.WithDictionaryHandle();
|
||||
// })
|
||||
/*.AddOpenTracing(option =>
|
||||
{
|
||||
option.CollectorUrl = "http://localhost:9618";
|
||||
@ -60,4 +64,15 @@
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,17 +52,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_specific_delegating_handler_singleton()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.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()
|
||||
{
|
||||
@ -74,17 +63,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
.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();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_services()
|
||||
{
|
||||
@ -231,15 +209,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
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();
|
||||
@ -262,13 +231,13 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
private void AddTransientGlobalDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddTransientDelegatingHandler<T>(true);
|
||||
_ocelotBuilder.AddDelegatingHandler<T>(true);
|
||||
}
|
||||
|
||||
private void AddSpecificTransientDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddTransientDelegatingHandler<T>();
|
||||
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||
}
|
||||
|
||||
private void ThenTheCorrectAdminPathIsRegitered()
|
||||
@ -365,13 +334,13 @@ namespace Ocelot.UnitTests.DependencyInjection
|
||||
private void AddGlobalDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddSingletonDelegatingHandler<T>(true);
|
||||
_ocelotBuilder.AddDelegatingHandler<T>(true);
|
||||
}
|
||||
|
||||
private void AddSpecificDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddSingletonDelegatingHandler<T>();
|
||||
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||
}
|
||||
|
||||
private void ThenAnOcelotBuilderIsReturned()
|
||||
|
Loading…
x
Reference in New Issue
Block a user