mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 03:38:16 +08:00
Delegating Handlers from container (#266)
* #259 quickly hacked poc for this together, needs tidying up maybe * #266 +semver: breaking removed adding delegating handler funcs directly...i feel from container is enough
This commit is contained in:
@ -3,16 +3,22 @@ using CacheManager.Core;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using Ocelot.Requester;
|
||||
|
||||
namespace Ocelot.DependencyInjection
|
||||
{
|
||||
public interface IOcelotBuilder
|
||||
{
|
||||
IOcelotBuilder AddStoreOcelotConfigurationInConsul();
|
||||
|
||||
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
|
||||
|
||||
IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings);
|
||||
|
||||
IOcelotAdministrationBuilder AddAdministration(string path, string secret);
|
||||
|
||||
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
||||
IOcelotBuilder AddDelegatingHandler(Func<DelegatingHandler> delegatingHandler);
|
||||
|
||||
IOcelotBuilder AddDelegatingHandler<T>() where T : DelegatingHandler;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ namespace Ocelot.DependencyInjection
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private readonly IConfiguration _configurationRoot;
|
||||
private readonly IDelegatingHandlerHandlerProvider _provider;
|
||||
|
||||
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
||||
{
|
||||
@ -120,8 +119,7 @@ namespace Ocelot.DependencyInjection
|
||||
_services.TryAddSingleton<IRequestMapper, RequestMapper>();
|
||||
_services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>();
|
||||
_services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>();
|
||||
_services.TryAddSingleton<IDelegatingHandlerHandlerProviderFactory, DelegatingHandlerHandlerProviderFactory>();
|
||||
_services.TryAddSingleton<IDelegatingHandlerHandlerHouse, DelegatingHandlerHandlerHouse>();
|
||||
_services.TryAddSingleton<IDelegatingHandlerHandlerFactory, DelegatingHandlerHandlerFactory>();
|
||||
|
||||
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
|
||||
// could maybe use a scoped data repository
|
||||
@ -144,9 +142,6 @@ namespace Ocelot.DependencyInjection
|
||||
_services.AddWebEncoders();
|
||||
_services.AddSingleton<IAdministrationPath>(new NullAdministrationPath());
|
||||
|
||||
//these get picked out later and added to http request
|
||||
_provider = new DelegatingHandlerHandlerProvider();
|
||||
_services.TryAddSingleton<IDelegatingHandlerHandlerProvider>(_provider);
|
||||
_services.TryAddSingleton<IMultiplexer, Multiplexer>();
|
||||
_services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>();
|
||||
_services.AddSingleton<ITracingHandlerFactory, TracingHandlerFactory>();
|
||||
@ -187,9 +182,10 @@ namespace Ocelot.DependencyInjection
|
||||
return new OcelotAdministrationBuilder(_services, _configurationRoot);
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddDelegatingHandler(Func<DelegatingHandler> delegatingHandler)
|
||||
public IOcelotBuilder AddDelegatingHandler<THandler>()
|
||||
where THandler : DelegatingHandler
|
||||
{
|
||||
_provider.Add(delegatingHandler);
|
||||
_services.AddSingleton<DelegatingHandler, THandler>();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Requester
|
||||
{
|
||||
public class DelegatingHandlerHandlerHouse : IDelegatingHandlerHandlerHouse
|
||||
{
|
||||
private readonly IDelegatingHandlerHandlerProviderFactory _factory;
|
||||
private readonly ConcurrentDictionary<string, IDelegatingHandlerHandlerProvider> _housed;
|
||||
|
||||
public DelegatingHandlerHandlerHouse(IDelegatingHandlerHandlerProviderFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
_housed = new ConcurrentDictionary<string, IDelegatingHandlerHandlerProvider>();
|
||||
}
|
||||
|
||||
public Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_housed.TryGetValue(request.ReRouteKey, out var provider))
|
||||
{
|
||||
//todo once day we might need a check here to see if we need to create a new provider
|
||||
provider = _housed[request.ReRouteKey];
|
||||
return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
|
||||
}
|
||||
|
||||
//todo - unit test for this
|
||||
var providerResponse = _factory.Get(request);
|
||||
|
||||
if (providerResponse.IsError)
|
||||
{
|
||||
return new ErrorResponse<IDelegatingHandlerHandlerProvider>(providerResponse.Errors);
|
||||
}
|
||||
|
||||
provider = providerResponse.Data;
|
||||
AddHoused(request.ReRouteKey, provider);
|
||||
return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<IDelegatingHandlerHandlerProvider>(new List<Error>()
|
||||
{
|
||||
new UnableToFindDelegatingHandlerProviderError($"unabe to find delegating handler provider for {request.ReRouteKey} exception is {ex}")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void AddHoused(string key, IDelegatingHandlerHandlerProvider provider)
|
||||
{
|
||||
_housed.AddOrUpdate(key, provider, (k, v) => provider);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Ocelot.Requester
|
||||
{
|
||||
public class DelegatingHandlerHandlerProvider : IDelegatingHandlerHandlerProvider
|
||||
{
|
||||
private readonly Dictionary<int, Func<DelegatingHandler>> _handlers;
|
||||
|
||||
public DelegatingHandlerHandlerProvider()
|
||||
{
|
||||
_handlers = new Dictionary<int, Func<DelegatingHandler>>();
|
||||
}
|
||||
|
||||
public void Add(Func<DelegatingHandler> handler)
|
||||
{
|
||||
var key = _handlers.Count == 0 ? 0 : _handlers.Count + 1;
|
||||
_handlers[key] = handler;
|
||||
}
|
||||
|
||||
public List<Func<DelegatingHandler>> Get()
|
||||
{
|
||||
return _handlers.Count > 0 ? _handlers.OrderBy(x => x.Key).Select(x => x.Value).ToList() : new List<Func<DelegatingHandler>>();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Requester.QoS;
|
||||
@ -7,38 +9,38 @@ using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Requester
|
||||
{
|
||||
public class DelegatingHandlerHandlerProviderFactory : IDelegatingHandlerHandlerProviderFactory
|
||||
public class DelegatingHandlerHandlerFactory : IDelegatingHandlerHandlerFactory
|
||||
{
|
||||
private readonly ITracingHandlerFactory _factory;
|
||||
private readonly IOcelotLoggerFactory _loggerFactory;
|
||||
private readonly IDelegatingHandlerHandlerProvider _allRoutesProvider;
|
||||
private readonly IQosProviderHouse _qosProviderHouse;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public DelegatingHandlerHandlerProviderFactory(IOcelotLoggerFactory loggerFactory,
|
||||
IDelegatingHandlerHandlerProvider allRoutesProvider,
|
||||
public DelegatingHandlerHandlerFactory(IOcelotLoggerFactory loggerFactory,
|
||||
ITracingHandlerFactory factory,
|
||||
IQosProviderHouse qosProviderHouse)
|
||||
IQosProviderHouse qosProviderHouse,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_factory = factory;
|
||||
_loggerFactory = loggerFactory;
|
||||
_allRoutesProvider = allRoutesProvider;
|
||||
_qosProviderHouse = qosProviderHouse;
|
||||
}
|
||||
|
||||
public Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request)
|
||||
public Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request)
|
||||
{
|
||||
var handlersAppliedToAll = _allRoutesProvider.Get();
|
||||
var handlersAppliedToAll = _serviceProvider.GetServices<DelegatingHandler>();
|
||||
|
||||
var provider = new DelegatingHandlerHandlerProvider();
|
||||
var handlers = new List<Func<DelegatingHandler>>();
|
||||
|
||||
foreach (var handler in handlersAppliedToAll)
|
||||
{
|
||||
provider.Add(handler);
|
||||
handlers.Add(() => handler);
|
||||
}
|
||||
|
||||
if (request.HttpHandlerOptions.UseTracing)
|
||||
{
|
||||
provider.Add(() => (DelegatingHandler)_factory.Get());
|
||||
handlers.Add(() => (DelegatingHandler)_factory.Get());
|
||||
}
|
||||
|
||||
if (request.IsQos)
|
||||
@ -47,13 +49,13 @@ namespace Ocelot.Requester
|
||||
|
||||
if (qosProvider.IsError)
|
||||
{
|
||||
return new ErrorResponse<IDelegatingHandlerHandlerProvider>(qosProvider.Errors);
|
||||
return new ErrorResponse<List<Func<DelegatingHandler>>>(qosProvider.Errors);
|
||||
}
|
||||
|
||||
provider.Add(() => new PollyCircuitBreakingDelegatingHandler(qosProvider.Data, _loggerFactory));
|
||||
handlers.Add(() => new PollyCircuitBreakingDelegatingHandler(qosProvider.Data, _loggerFactory));
|
||||
}
|
||||
|
||||
return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
|
||||
return new OkResponse<List<Func<DelegatingHandler>>>(handlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,11 @@ namespace Ocelot.Requester
|
||||
{
|
||||
public class HttpClientBuilder : IHttpClientBuilder
|
||||
{
|
||||
private readonly IDelegatingHandlerHandlerHouse _house;
|
||||
private readonly IDelegatingHandlerHandlerFactory _factory;
|
||||
|
||||
public HttpClientBuilder(IDelegatingHandlerHandlerHouse house)
|
||||
public HttpClientBuilder(IDelegatingHandlerHandlerFactory house)
|
||||
{
|
||||
_house = house;
|
||||
_factory = house;
|
||||
}
|
||||
|
||||
public IHttpClient Create(DownstreamReRoute request)
|
||||
@ -24,11 +24,9 @@ namespace Ocelot.Requester
|
||||
|
||||
private HttpMessageHandler CreateHttpMessageHandler(HttpMessageHandler httpMessageHandler, DownstreamReRoute request)
|
||||
{
|
||||
var provider = _house.Get(request);
|
||||
|
||||
var handlers = provider.Data.Get();
|
||||
|
||||
//todo handle error
|
||||
var handlers = _factory.Get(request).Data;
|
||||
|
||||
handlers
|
||||
.Select(handler => handler)
|
||||
.Reverse()
|
||||
|
@ -13,20 +13,20 @@ namespace Ocelot.Requester
|
||||
{
|
||||
private readonly IHttpClientCache _cacheHandlers;
|
||||
private readonly IOcelotLogger _logger;
|
||||
private readonly IDelegatingHandlerHandlerHouse _house;
|
||||
private readonly IDelegatingHandlerHandlerFactory _factory;
|
||||
|
||||
public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
|
||||
IHttpClientCache cacheHandlers,
|
||||
IDelegatingHandlerHandlerHouse house)
|
||||
IDelegatingHandlerHandlerFactory house)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
|
||||
_cacheHandlers = cacheHandlers;
|
||||
_house = house;
|
||||
_factory = house;
|
||||
}
|
||||
|
||||
public async Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext request)
|
||||
{
|
||||
var builder = new HttpClientBuilder(_house);
|
||||
var builder = new HttpClientBuilder(_factory);
|
||||
|
||||
var cacheKey = GetCacheKey(request);
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Requester
|
||||
{
|
||||
public interface IDelegatingHandlerHandlerHouse
|
||||
{
|
||||
Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Ocelot.Requester
|
||||
{
|
||||
public interface IDelegatingHandlerHandlerProvider
|
||||
{
|
||||
void Add(Func<DelegatingHandler> handler);
|
||||
List<Func<DelegatingHandler>> Get();
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.Requester
|
||||
{
|
||||
public interface IDelegatingHandlerHandlerProviderFactory
|
||||
public interface IDelegatingHandlerHandlerFactory
|
||||
{
|
||||
Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request);
|
||||
Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user