Feature/automatic routes with sd (#351)

* #340 started looking at supporting automatic routing when using service discovery

* #340 getting old routing tests to pass

* #340 renamed stuff to provider rather than finder, as its not longer finding anything

* #340 working towards supporting dynamic routing

* #340 loads of refactoring to make configuration work with dynamic routing

* #340 refactor consul config code so the registry class owns it

* #340 default to consul to maintain backwards compat

* #340 added docs, finished this branches todos
This commit is contained in:
Tom Pallister
2018-05-14 21:26:10 +01:00
committed by GitHub
parent dadb43ef6f
commit 1e2e953b2c
64 changed files with 2082 additions and 1221 deletions

View File

@ -9,7 +9,7 @@ namespace Ocelot.Configuration.Builder
public class DownstreamReRouteBuilder
{
private AuthenticationOptions _authenticationOptions;
private string _reRouteKey;
private string _loadBalancerKey;
private string _downstreamPathTemplate;
private string _upstreamTemplate;
private UpstreamPathTemplate _upstreamTemplatePattern;
@ -25,7 +25,6 @@ namespace Ocelot.Configuration.Builder
private CacheOptions _fileCacheOptions;
private string _downstreamScheme;
private LoadBalancerOptions _loadBalancerOptions;
private bool _useQos;
private QoSOptions _qosOptions;
private HttpHandlerOptions _httpHandlerOptions;
private bool _enableRateLimiting;
@ -41,7 +40,6 @@ namespace Ocelot.Configuration.Builder
private List<AddHeader> _addHeadersToDownstream;
private List<AddHeader> _addHeadersToUpstream;
private bool _dangerousAcceptAnyServerCertificateValidator;
private string _qosKey;
public DownstreamReRouteBuilder()
{
@ -153,27 +151,15 @@ namespace Ocelot.Configuration.Builder
return this;
}
public DownstreamReRouteBuilder WithIsQos(bool input)
{
_useQos = input;
return this;
}
public DownstreamReRouteBuilder WithQosOptions(QoSOptions input)
{
_qosOptions = input;
return this;
}
public DownstreamReRouteBuilder WithReRouteKey(string reRouteKey)
public DownstreamReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
{
_reRouteKey = reRouteKey;
return this;
}
public DownstreamReRouteBuilder WithQosKey(string qosKey)
{
_qosKey = qosKey;
_loadBalancerKey = loadBalancerKey;
return this;
}
@ -267,7 +253,6 @@ namespace Ocelot.Configuration.Builder
_httpHandlerOptions,
_useServiceDiscovery,
_enableRateLimiting,
_useQos,
_qosOptions,
_downstreamScheme,
_requestIdHeaderKey,
@ -283,12 +268,11 @@ namespace Ocelot.Configuration.Builder
_isAuthorised,
_authenticationOptions,
new PathTemplate(_downstreamPathTemplate),
_reRouteKey,
_loadBalancerKey,
_delegatingHandlers,
_addHeadersToDownstream,
_addHeadersToUpstream,
_dangerousAcceptAnyServerCertificateValidator,
_qosKey);
_dangerousAcceptAnyServerCertificateValidator);
}
}
}

View File

@ -6,7 +6,9 @@
private int _durationOfBreak;
private int _timeoutValue;
private int _timeoutValue;
private string _key;
public QoSOptionsBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
{
@ -26,9 +28,15 @@
return this;
}
public QoSOptionsBuilder WithKey(string input)
{
_key = input;
return this;
}
public QoSOptions Build()
{
return new QoSOptions(_exceptionsAllowedBeforeBreaking, _durationOfBreak, _timeoutValue);
return new QoSOptions(_exceptionsAllowedBeforeBreaking, _durationOfBreak, _timeoutValue, _key);
}
}
}

View File

@ -5,7 +5,6 @@ namespace Ocelot.Configuration.Builder
private bool _isAuthenticated;
private bool _isAuthorised;
private bool _isCached;
private bool _isQoS;
private bool _enableRateLimiting;
public ReRouteOptionsBuilder WithIsCached(bool isCached)
@ -26,12 +25,6 @@ namespace Ocelot.Configuration.Builder
return this;
}
public ReRouteOptionsBuilder WithIsQos(bool isQoS)
{
_isQoS = isQoS;
return this;
}
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
{
_enableRateLimiting = enableRateLimiting;
@ -40,7 +33,7 @@ namespace Ocelot.Configuration.Builder
public ReRouteOptions Build()
{
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _isQoS, _enableRateLimiting);
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting);
}
}
}
}

View File

@ -104,8 +104,22 @@ namespace Ocelot.Configuration.Creator
}
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
var config = new InternalConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey);
var lbOptions = CreateLoadBalancerOptions(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);
var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);
var config = new InternalConfiguration(reRoutes,
_adminPath.Path,
serviceProviderConfiguration,
fileConfiguration.GlobalConfiguration.RequestIdKey,
lbOptions,
fileConfiguration.GlobalConfiguration.DownstreamScheme,
qosOptions,
httpHandlerOptions
);
return new OkResponse<IInternalConfiguration>(config);
}
@ -160,8 +174,6 @@ namespace Ocelot.Configuration.Creator
var reRouteKey = CreateReRouteKey(fileReRoute);
var qosKey = CreateQosKey(fileReRoute);
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
@ -172,19 +184,19 @@ namespace Ocelot.Configuration.Creator
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
var qosOptions = _qosOptionsCreator.Create(fileReRoute);
var qosOptions = _qosOptionsCreator.Create(fileReRoute.QoSOptions, fileReRoute.UpstreamPathTemplate, fileReRoute.UpstreamHttpMethod.ToArray());
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
var region = _regionCreator.Create(fileReRoute);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute.HttpHandlerOptions);
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
var lbOptions = CreateLoadBalancerOptions(fileReRoute);
var lbOptions = CreateLoadBalancerOptions(fileReRoute.LoadBalancerOptions);
var reRoute = new DownstreamReRouteBuilder()
.WithKey(fileReRoute.Key)
@ -205,9 +217,7 @@ namespace Ocelot.Configuration.Creator
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
.WithLoadBalancerOptions(lbOptions)
.WithDownstreamAddresses(downstreamAddresses)
.WithReRouteKey(reRouteKey)
.WithQosKey(qosKey)
.WithIsQos(fileReRouteOptions.IsQos)
.WithLoadBalancerKey(reRouteKey)
.WithQosOptions(qosOptions)
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
.WithRateLimitOptions(rateLimitOption)
@ -226,9 +236,13 @@ namespace Ocelot.Configuration.Creator
return reRoute;
}
private LoadBalancerOptions CreateLoadBalancerOptions(FileReRoute fileReRoute)
private LoadBalancerOptions CreateLoadBalancerOptions(FileLoadBalancerOptions options)
{
return new LoadBalancerOptions(fileReRoute.LoadBalancerOptions.Type, fileReRoute.LoadBalancerOptions.Key, fileReRoute.LoadBalancerOptions.Expiry);
return new LoadBalancerOptionsBuilder()
.WithType(options.Type)
.WithKey(options.Key)
.WithExpiryInMs(options.Expiry)
.Build();
}
private string CreateReRouteKey(FileReRoute fileReRoute)
@ -238,14 +252,7 @@ namespace Ocelot.Configuration.Creator
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
}
return CreateQosKey(fileReRoute);
}
private string CreateQosKey(FileReRoute fileReRoute)
{
//note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
return loadBalancerKey;
return $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
}
}
}

View File

@ -6,19 +6,19 @@ namespace Ocelot.Configuration.Creator
{
public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator
{
private IServiceTracer _tracer;
private readonly IServiceTracer _tracer;
public HttpHandlerOptionsCreator(IServiceTracer tracer)
{
_tracer = tracer;
}
public HttpHandlerOptions Create(FileReRoute fileReRoute)
public HttpHandlerOptions Create(FileHttpHandlerOptions options)
{
var useTracing = _tracer.GetType() != typeof(FakeServiceTracer) ? fileReRoute.HttpHandlerOptions.UseTracing : false;
var useTracing = _tracer.GetType() != typeof(FakeServiceTracer) && options.UseTracing;
return new HttpHandlerOptions(fileReRoute.HttpHandlerOptions.AllowAutoRedirect,
fileReRoute.HttpHandlerOptions.UseCookieContainer, useTracing);
return new HttpHandlerOptions(options.AllowAutoRedirect,
options.UseCookieContainer, useTracing);
}
}
}

View File

@ -7,6 +7,6 @@ namespace Ocelot.Configuration.Creator
/// </summary>
public interface IHttpHandlerOptionsCreator
{
HttpHandlerOptions Create(FileReRoute fileReRoute);
HttpHandlerOptions Create(FileHttpHandlerOptions fileReRoute);
}
}

View File

@ -4,6 +4,8 @@ namespace Ocelot.Configuration.Creator
{
public interface IQoSOptionsCreator
{
QoSOptions Create(FileReRoute fileReRoute);
QoSOptions Create(FileQoSOptions options);
QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods);
QoSOptions Create(QoSOptions options, string pathTemplate, string[] httpMethods);
}
}
}

View File

@ -6,4 +6,4 @@ namespace Ocelot.Configuration.Creator
{
ReRouteOptions Create(FileReRoute fileReRoute);
}
}
}

View File

@ -1,17 +1,47 @@
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using System.Linq;
public class QoSOptionsCreator : IQoSOptionsCreator
{
public QoSOptions Create(FileReRoute fileReRoute)
public QoSOptions Create(FileQoSOptions options)
{
return new QoSOptionsBuilder()
.WithExceptionsAllowedBeforeBreaking(fileReRoute.QoSOptions.ExceptionsAllowedBeforeBreaking)
.WithDurationOfBreak(fileReRoute.QoSOptions.DurationOfBreak)
.WithTimeoutValue(fileReRoute.QoSOptions.TimeoutValue)
.WithExceptionsAllowedBeforeBreaking(options.ExceptionsAllowedBeforeBreaking)
.WithDurationOfBreak(options.DurationOfBreak)
.WithTimeoutValue(options.TimeoutValue)
.Build();
}
public QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods)
{
var key = CreateKey(pathTemplate, httpMethods);
return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking);
}
public QoSOptions Create(QoSOptions options, string pathTemplate, string[] httpMethods)
{
var key = CreateKey(pathTemplate, httpMethods);
return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking);
}
private QoSOptions Map(string key, int timeoutValue, int durationOfBreak, int exceptionsAllowedBeforeBreaking)
{
return new QoSOptionsBuilder()
.WithExceptionsAllowedBeforeBreaking(exceptionsAllowedBeforeBreaking)
.WithDurationOfBreak(durationOfBreak)
.WithTimeoutValue(timeoutValue)
.WithKey(key)
.Build();
}
private string CreateKey(string pathTemplate, string[] httpMethods)
{
return $"{pathTemplate.FirstOrDefault()}|{string.Join(",", httpMethods)}";
}
}
}
}

View File

@ -10,14 +10,12 @@ namespace Ocelot.Configuration.Creator
var isAuthenticated = IsAuthenticated(fileReRoute);
var isAuthorised = IsAuthorised(fileReRoute);
var isCached = IsCached(fileReRoute);
var isQos = IsQoS(fileReRoute);
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
var options = new ReRouteOptionsBuilder()
.WithIsAuthenticated(isAuthenticated)
.WithIsAuthorised(isAuthorised)
.WithIsCached(isCached)
.WithIsQos(isQos)
.WithRateLimiting(enableRateLimiting)
.Build();
@ -29,11 +27,6 @@ namespace Ocelot.Configuration.Creator
return (fileReRoute.RateLimitOptions != null && fileReRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
}
private bool IsQoS(FileReRoute fileReRoute)
{
return fileReRoute.QoSOptions?.ExceptionsAllowedBeforeBreaking > 0 && fileReRoute.QoSOptions?.TimeoutValue > 0;
}
private bool IsAuthenticated(FileReRoute fileReRoute)
{
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.AuthenticationProviderKey);
@ -48,5 +41,5 @@ namespace Ocelot.Configuration.Creator
{
return fileReRoute.FileCacheOptions.TtlSeconds > 0;
}
}
}
}
}

View File

@ -7,12 +7,12 @@ namespace Ocelot.Configuration.Creator
{
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration)
{
//todo log or return error here dont just default to something that wont work..
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
var port = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
var host = globalConfiguration?.ServiceDiscoveryProvider?.Host ?? "consul";
return new ServiceProviderConfigurationBuilder()
.WithHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
.WithPort(serviceProviderPort)
.WithHost(host)
.WithPort(port)
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)

View File

@ -16,8 +16,7 @@ namespace Ocelot.Configuration
HttpHandlerOptions httpHandlerOptions,
bool useServiceDiscovery,
bool enableEndpointEndpointRateLimiting,
bool isQos,
QoSOptions qosOptionsOptions,
QoSOptions qosOptions,
string downstreamScheme,
string requestIdKey,
bool isCached,
@ -36,8 +35,7 @@ namespace Ocelot.Configuration
List<string> delegatingHandlers,
List<AddHeader> addHeadersToDownstream,
List<AddHeader> addHeadersToUpstream,
bool dangerousAcceptAnyServerCertificateValidator,
string qosKey)
bool dangerousAcceptAnyServerCertificateValidator)
{
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
AddHeadersToDownstream = addHeadersToDownstream;
@ -51,8 +49,7 @@ namespace Ocelot.Configuration
HttpHandlerOptions = httpHandlerOptions;
UseServiceDiscovery = useServiceDiscovery;
EnableEndpointEndpointRateLimiting = enableEndpointEndpointRateLimiting;
IsQos = isQos;
QosOptionsOptions = qosOptionsOptions;
QosOptions = qosOptions;
DownstreamScheme = downstreamScheme;
RequestIdKey = requestIdKey;
IsCached = isCached;
@ -69,10 +66,8 @@ namespace Ocelot.Configuration
DownstreamPathTemplate = downstreamPathTemplate;
LoadBalancerKey = loadBalancerKey;
AddHeadersToUpstream = addHeadersToUpstream;
QosKey = qosKey;
}
public string QosKey { get; }
public string Key { get; }
public PathTemplate UpstreamPathTemplate { get; }
public List<HeaderFindAndReplace> UpstreamHeadersFindAndReplace { get; }
@ -82,8 +77,7 @@ namespace Ocelot.Configuration
public HttpHandlerOptions HttpHandlerOptions { get; }
public bool UseServiceDiscovery { get; }
public bool EnableEndpointEndpointRateLimiting { get; }
public bool IsQos { get; }
public QoSOptions QosOptionsOptions { get; }
public QoSOptions QosOptions { get; }
public string DownstreamScheme { get; }
public string RequestIdKey { get; }
public bool IsCached { get; }

View File

@ -6,6 +6,9 @@
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider();
RateLimitOptions = new FileRateLimitOptions();
LoadBalancerOptions = new FileLoadBalancerOptions();
QoSOptions = new FileQoSOptions();
HttpHandlerOptions = new FileHttpHandlerOptions();
}
public string RequestIdKey { get; set; }
@ -13,7 +16,15 @@
public FileServiceDiscoveryProvider ServiceDiscoveryProvider { get;set; }
public FileRateLimitOptions RateLimitOptions { get; set; }
public FileQoSOptions QoSOptions { get; set; }
public string BaseUrl { get ;set; }
public FileLoadBalancerOptions LoadBalancerOptions { get; set; }
public string DownstreamScheme { get; set; }
public FileHttpHandlerOptions HttpHandlerOptions { get; set; }
}
}

View File

@ -0,0 +1,32 @@
namespace Ocelot.Configuration
{
public class HttpHandlerOptionsBuilder
{
private bool _allowAutoRedirect;
private bool _useCookieContainer;
private bool _useTracing;
public HttpHandlerOptionsBuilder WithAllowAutoRedirect(bool input)
{
_allowAutoRedirect = input;
return this;
}
public HttpHandlerOptionsBuilder WithUseCookieContainer(bool input)
{
_useCookieContainer = input;
return this;
}
public HttpHandlerOptionsBuilder WithUseTracing(bool input)
{
_useTracing = input;
return this;
}
public HttpHandlerOptions Build()
{
return new HttpHandlerOptions(_allowAutoRedirect, _useCookieContainer, _useTracing);
}
}
}

View File

@ -5,8 +5,19 @@ namespace Ocelot.Configuration
public interface IInternalConfiguration
{
List<ReRoute> ReRoutes { get; }
string AdministrationPath {get;}
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
string RequestId {get;}
LoadBalancerOptions LoadBalancerOptions { get; }
string DownstreamScheme { get; }
QoSOptions QoSOptions { get; }
HttpHandlerOptions HttpHandlerOptions { get; }
}
}

View File

@ -4,17 +4,33 @@ namespace Ocelot.Configuration
{
public class InternalConfiguration : IInternalConfiguration
{
public InternalConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId)
public InternalConfiguration(
List<ReRoute> reRoutes,
string administrationPath,
ServiceProviderConfiguration serviceProviderConfiguration,
string requestId,
LoadBalancerOptions loadBalancerOptions,
string downstreamScheme,
QoSOptions qoSOptions,
HttpHandlerOptions httpHandlerOptions)
{
ReRoutes = reRoutes;
AdministrationPath = administrationPath;
ServiceProviderConfiguration = serviceProviderConfiguration;
RequestId = requestId;
LoadBalancerOptions = loadBalancerOptions;
DownstreamScheme = downstreamScheme;
QoSOptions = qoSOptions;
HttpHandlerOptions = httpHandlerOptions;
}
public List<ReRoute> ReRoutes { get; }
public string AdministrationPath {get;}
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
public string RequestId {get;}
public LoadBalancerOptions LoadBalancerOptions { get; }
public string DownstreamScheme { get; }
public QoSOptions QoSOptions { get; }
public HttpHandlerOptions HttpHandlerOptions { get; }
}
}

View File

@ -0,0 +1,32 @@
namespace Ocelot.Configuration
{
public class LoadBalancerOptionsBuilder
{
private string _type;
private string _key;
private int _expiryInMs;
public LoadBalancerOptionsBuilder WithType(string type)
{
_type = type;
return this;
}
public LoadBalancerOptionsBuilder WithKey(string key)
{
_key = key;
return this;
}
public LoadBalancerOptionsBuilder WithExpiryInMs(int expiryInMs)
{
_expiryInMs = expiryInMs;
return this;
}
public LoadBalancerOptions Build()
{
return new LoadBalancerOptions(_type, _key, _expiryInMs);
}
}
}

View File

@ -8,12 +8,14 @@ namespace Ocelot.Configuration
int exceptionsAllowedBeforeBreaking,
int durationofBreak,
int timeoutValue,
string key,
TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
{
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
DurationOfBreak = durationofBreak;
TimeoutValue = timeoutValue;
TimeoutStrategy = timeoutStrategy;
Key = key;
}
public int ExceptionsAllowedBeforeBreaking { get; }
@ -23,5 +25,8 @@ namespace Ocelot.Configuration
public int TimeoutValue { get; }
public TimeoutStrategy TimeoutStrategy { get; }
public bool UseQos => ExceptionsAllowedBeforeBreaking > 0 && TimeoutValue > 0;
public string Key { get; }
}
}

View File

@ -2,19 +2,17 @@ namespace Ocelot.Configuration
{
public class ReRouteOptions
{
public ReRouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isQos, bool isEnableRateLimiting)
public ReRouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isEnableRateLimiting)
{
IsAuthenticated = isAuthenticated;
IsAuthorised = isAuthorised;
IsCached = isCached;
IsQos = isQos;
EnableRateLimiting = isEnableRateLimiting;
}
public bool IsAuthenticated { get; private set; }
public bool IsAuthorised { get; private set; }
public bool IsCached { get; private set; }
public bool IsQos { get; private set; }
public bool EnableRateLimiting { get; private set; }
}
}

View File

@ -30,20 +30,18 @@ namespace Ocelot.Configuration.Repository
var internalConfig = repo.Get();
_configurationKey = "InternalConfiguration";
var consulHost = "localhost";
var consulPort = 8500;
string token = null;
if (!internalConfig.IsError)
{
consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host;
consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort;
token = internalConfig.Data.ServiceProviderConfiguration?.Token;
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.ConfigurationKey) ?
internalConfig.Data.ServiceProviderConfiguration?.ConfigurationKey : _configurationKey;
token = internalConfig.Data.ServiceProviderConfiguration.Token;
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey) ?
internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey : _configurationKey;
}
var config = new ConsulRegistryConfiguration(consulHost, consulPort, _configurationKey, token);
var config = new ConsulRegistryConfiguration(internalConfig.Data.ServiceProviderConfiguration.Host,
internalConfig.Data.ServiceProviderConfiguration.Port, _configurationKey, token);
_consul = factory.Get(config);
}

View File

@ -103,7 +103,9 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
_services.TryAddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
_services.TryAddSingleton<IDownstreamPathPlaceholderReplacer, DownstreamTemplatePathPlaceholderReplacer>();
_services.TryAddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
_services.AddSingleton<IDownstreamRouteProvider, DownstreamRouteFinder>();
_services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>();
_services.TryAddSingleton<IDownstreamRouteProviderFactory, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteProviderFactory>();
_services.TryAddSingleton<IHttpRequester, HttpClientHttpRequester>();
_services.TryAddSingleton<IHttpResponder, HttpContextResponder>();
_services.TryAddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>();

View File

@ -0,0 +1,97 @@
namespace Ocelot.DownstreamRouteFinder.Finder
{
using System.Collections.Generic;
using Configuration;
using Configuration.Builder;
using Configuration.Creator;
using Configuration.File;
using LoadBalancer.LoadBalancers;
using Responses;
using UrlMatcher;
public class DownstreamRouteCreator : IDownstreamRouteProvider
{
private readonly IQoSOptionsCreator _qoSOptionsCreator;
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
{
_qoSOptionsCreator = qoSOptionsCreator;
}
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
{
var serviceName = GetServiceName(upstreamUrlPath);
var downstreamPath = GetDownstreamPath(upstreamUrlPath);
if(HasQueryString(downstreamPath))
{
downstreamPath = RemoveQueryString(downstreamPath);
}
var downstreamPathForKeys = $"/{serviceName}{downstreamPath}";
var loadBalancerKey = CreateLoadBalancerKey(downstreamPathForKeys, upstreamHttpMethod, configuration.LoadBalancerOptions);
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new []{ upstreamHttpMethod });
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithServiceName(serviceName)
.WithLoadBalancerKey(loadBalancerKey)
.WithDownstreamPathTemplate(downstreamPath)
.WithUseServiceDiscovery(true)
.WithHttpHandlerOptions(configuration.HttpHandlerOptions)
.WithQosOptions(qosOptions)
.WithDownstreamScheme(configuration.DownstreamScheme)
.WithLoadBalancerOptions(configuration.LoadBalancerOptions)
.Build();
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamHttpMethod(new List<string>(){ upstreamHttpMethod })
.Build();
return new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
}
private static string RemoveQueryString(string downstreamPath)
{
return downstreamPath
.Substring(0, downstreamPath.IndexOf('?'));
}
private static bool HasQueryString(string downstreamPath)
{
return downstreamPath.Contains("?");
}
private static string GetDownstreamPath(string upstreamUrlPath)
{
return upstreamUrlPath
.Substring(upstreamUrlPath.IndexOf('/', 1));
}
private static string GetServiceName(string upstreamUrlPath)
{
return upstreamUrlPath
.Substring(1, upstreamUrlPath.IndexOf('/', 1))
.TrimEnd('/');
}
private string CreateLoadBalancerKey(string downstreamTemplatePath, string httpMethod, LoadBalancerOptions loadBalancerOptions)
{
if (!string.IsNullOrEmpty(loadBalancerOptions.Type) && !string.IsNullOrEmpty(loadBalancerOptions.Key) && loadBalancerOptions.Type == nameof(CookieStickySessions))
{
return $"{nameof(CookieStickySessions)}:{loadBalancerOptions.Key}";
}
return CreateQoSKey(downstreamTemplatePath, httpMethod);
}
private string CreateQoSKey(string downstreamTemplatePath, string httpMethod)
{
var loadBalancerKey = $"{downstreamTemplatePath}|{httpMethod}";
return loadBalancerKey;
}
}
}

View File

@ -1,62 +1,62 @@
using System.Collections.Generic;
using System.Linq;
using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Errors;
using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.Finder
{
public class DownstreamRouteFinder : IDownstreamRouteFinder
{
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
public DownstreamRouteFinder(IUrlPathToUrlTemplateMatcher urlMatcher, IPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder)
{
_urlMatcher = urlMatcher;
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
}
public Response<DownstreamRoute> FindDownstreamRoute(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
{
var downstreamRoutes = new List<DownstreamRoute>();
var applicableReRoutes = configuration.ReRoutes
.Where(r => RouteIsApplicableToThisRequest(r, httpMethod, upstreamHost))
.OrderByDescending(x => x.UpstreamTemplatePattern.Priority);
foreach (var reRoute in applicableReRoutes)
{
var urlMatch = _urlMatcher.Match(path, reRoute.UpstreamTemplatePattern.Template);
if (urlMatch.Data.Match)
{
downstreamRoutes.Add(GetPlaceholderNamesAndValues(path, reRoute));
}
}
if (downstreamRoutes.Any())
{
var notNullOption = downstreamRoutes.FirstOrDefault(x => !string.IsNullOrEmpty(x.ReRoute.UpstreamHost));
var nullOption = downstreamRoutes.FirstOrDefault(x => string.IsNullOrEmpty(x.ReRoute.UpstreamHost));
return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
}
return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(path, httpMethod));
}
private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
{
return reRoute.UpstreamHttpMethod.Count == 0 || reRoute.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(httpMethod.ToLower()) && !(!string.IsNullOrEmpty(reRoute.UpstreamHost) && reRoute.UpstreamHost != upstreamHost);
}
private DownstreamRoute GetPlaceholderNamesAndValues(string path, ReRoute reRoute)
{
var templatePlaceholderNameAndValues = _placeholderNameAndValueFinder.Find(path, reRoute.UpstreamPathTemplate.Value);
return new DownstreamRoute(templatePlaceholderNameAndValues.Data, reRoute);
}
}
}
using System.Collections.Generic;
using System.Linq;
using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Errors;
using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.Finder
{
public class DownstreamRouteFinder : IDownstreamRouteProvider
{
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
public DownstreamRouteFinder(IUrlPathToUrlTemplateMatcher urlMatcher, IPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder)
{
_urlMatcher = urlMatcher;
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
}
public Response<DownstreamRoute> Get(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
{
var downstreamRoutes = new List<DownstreamRoute>();
var applicableReRoutes = configuration.ReRoutes
.Where(r => RouteIsApplicableToThisRequest(r, httpMethod, upstreamHost))
.OrderByDescending(x => x.UpstreamTemplatePattern.Priority);
foreach (var reRoute in applicableReRoutes)
{
var urlMatch = _urlMatcher.Match(path, reRoute.UpstreamTemplatePattern.Template);
if (urlMatch.Data.Match)
{
downstreamRoutes.Add(GetPlaceholderNamesAndValues(path, reRoute));
}
}
if (downstreamRoutes.Any())
{
var notNullOption = downstreamRoutes.FirstOrDefault(x => !string.IsNullOrEmpty(x.ReRoute.UpstreamHost));
var nullOption = downstreamRoutes.FirstOrDefault(x => string.IsNullOrEmpty(x.ReRoute.UpstreamHost));
return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
}
return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(path, httpMethod));
}
private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
{
return reRoute.UpstreamHttpMethod.Count == 0 || reRoute.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(httpMethod.ToLower()) && !(!string.IsNullOrEmpty(reRoute.UpstreamHost) && reRoute.UpstreamHost != upstreamHost);
}
private DownstreamRoute GetPlaceholderNamesAndValues(string path, ReRoute reRoute)
{
var templatePlaceholderNameAndValues = _placeholderNameAndValueFinder.Find(path, reRoute.UpstreamPathTemplate.Value);
return new DownstreamRoute(templatePlaceholderNameAndValues.Data, reRoute);
}
}
}

View File

@ -0,0 +1,38 @@
namespace Ocelot.DownstreamRouteFinder.Finder
{
using System;
using System.Collections.Generic;
using System.Linq;
using Configuration;
using Microsoft.Extensions.DependencyInjection;
public class DownstreamRouteProviderFactory : IDownstreamRouteProviderFactory
{
private readonly Dictionary<string, IDownstreamRouteProvider> _providers;
public DownstreamRouteProviderFactory(IServiceProvider provider)
{
_providers = provider.GetServices<IDownstreamRouteProvider>().ToDictionary(x => x.GetType().Name);
}
public IDownstreamRouteProvider Get(IInternalConfiguration config)
{
if(!config.ReRoutes.Any() && IsServiceDiscovery(config.ServiceProviderConfiguration))
{
return _providers[nameof(DownstreamRouteCreator)];
}
return _providers[nameof(DownstreamRouteFinder)];
}
private bool IsServiceDiscovery(ServiceProviderConfiguration config)
{
if(!string.IsNullOrEmpty(config?.Host) || config?.Port > 0)
{
return true;
}
return false;
}
}
}

View File

@ -1,11 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration;
using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.Finder
{
public interface IDownstreamRouteFinder
{
Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
}
}

View File

@ -0,0 +1,11 @@
using System.Threading.Tasks;
using Ocelot.Configuration;
using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.Finder
{
public interface IDownstreamRouteProvider
{
Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
}
}

View File

@ -0,0 +1,9 @@
namespace Ocelot.DownstreamRouteFinder.Finder
{
using Configuration;
public interface IDownstreamRouteProviderFactory
{
IDownstreamRouteProvider Get(IInternalConfiguration config);
}
}

View File

@ -1,69 +1,60 @@
using System.Threading.Tasks;
using System.Linq;
using Ocelot.Configuration.Repository;
using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Logging;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.DownstreamRouteFinder.Middleware
{
public class DownstreamRouteFinderMiddleware : OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
private readonly IInternalConfigurationRepository _repo;
private readonly IMultiplexer _multiplexer;
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IDownstreamRouteFinder downstreamRouteFinder,
IInternalConfigurationRepository repo,
IMultiplexer multiplexer)
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
{
_repo = repo;
_multiplexer = multiplexer;
_next = next;
_downstreamRouteFinder = downstreamRouteFinder;
}
public async Task Invoke(DownstreamContext context)
{
var upstreamUrlPath = context.HttpContext.Request.Path.ToString();
var upstreamHost = context.HttpContext.Request.Headers["Host"];
var configuration = _repo.Get();
if (configuration.IsError)
{
Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
SetPipelineError(context, configuration.Errors);
return;
}
context.ServiceProviderConfiguration = configuration.Data.ServiceProviderConfiguration;
Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.HttpContext.Request.Method, configuration.Data, upstreamHost);
if (downstreamRoute.IsError)
{
Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
SetPipelineError(context, downstreamRoute.Errors);
return;
}
var downstreamPathTemplates = string.Join(", ", downstreamRoute.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));
Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");
context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;
await _multiplexer.Multiplex(context, downstreamRoute.Data.ReRoute, _next);
}
}
}
using System.Threading.Tasks;
using System.Linq;
using Ocelot.Configuration.Repository;
using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Logging;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.DownstreamRouteFinder.Middleware
{
public class DownstreamRouteFinderMiddleware : OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
private readonly IDownstreamRouteProviderFactory _factory;
private readonly IInternalConfigurationRepository _repo;
private readonly IMultiplexer _multiplexer;
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IDownstreamRouteProviderFactory downstreamRouteFinder,
IInternalConfigurationRepository repo,
IMultiplexer multiplexer)
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
{
_repo = repo;
_multiplexer = multiplexer;
_next = next;
_factory = downstreamRouteFinder;
}
public async Task Invoke(DownstreamContext context)
{
var upstreamUrlPath = context.HttpContext.Request.Path.ToString();
var upstreamHost = context.HttpContext.Request.Headers["Host"];
Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
var provider = _factory.Get(context.Configuration);
var downstreamRoute = provider.Get(upstreamUrlPath, context.HttpContext.Request.Method, context.Configuration, upstreamHost);
if (downstreamRoute.IsError)
{
Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
SetPipelineError(context, downstreamRoute.Errors);
return;
}
var downstreamPathTemplates = string.Join(", ", downstreamRoute.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));
Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");
context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;
await _multiplexer.Multiplex(context, downstreamRoute.Data.ReRoute, _next);
}
}
}

View File

@ -73,7 +73,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
private static bool ServiceFabricRequest(DownstreamContext context)
{
return context.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery;
return context.Configuration.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery;
}
private static bool RequestForStatefullService(string query)

View File

@ -9,6 +9,8 @@ using Ocelot.Middleware;
namespace Ocelot.Errors.Middleware
{
using Configuration;
/// <summary>
/// Catches all unhandled exceptions thrown by middleware, logs and returns a 500
/// </summary>
@ -32,8 +34,20 @@ namespace Ocelot.Errors.Middleware
public async Task Invoke(DownstreamContext context)
{
try
{
TrySetGlobalRequestId(context);
{
//try and get the global request id and set it for logs...
//should this basically be immutable per request...i guess it should!
//first thing is get config
var configuration = _configRepo.Get();
if (configuration.IsError)
{
throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
}
TrySetGlobalRequestId(context, configuration.Data);
context.Configuration = configuration.Data;
Logger.LogDebug("ocelot pipeline started");
@ -53,19 +67,9 @@ namespace Ocelot.Errors.Middleware
Logger.LogDebug("ocelot pipeline finished");
}
private void TrySetGlobalRequestId(DownstreamContext context)
private void TrySetGlobalRequestId(DownstreamContext context, IInternalConfiguration configuration)
{
//try and get the global request id and set it for logs...
//should this basically be immutable per request...i guess it should!
//first thing is get config
var configuration = _configRepo.Get();
if(configuration.IsError)
{
throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
}
var key = configuration.Data.RequestId;
var key = configuration.RequestId;
if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
{

View File

@ -18,7 +18,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
{
//todo no point spinning a task up here, also first or default could be null..
//todo first or default could be null..
if (_services == null || _services.Count == 0)
{
return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer"));

View File

@ -22,7 +22,7 @@ namespace Ocelot.LoadBalancer.Middleware
public async Task Invoke(DownstreamContext context)
{
var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration);
var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.Configuration.ServiceProviderConfiguration);
if(loadBalancer.IsError)
{
Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");

View File

@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Errors;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Request.Middleware;
namespace Ocelot.Middleware
@ -20,8 +17,6 @@ namespace Ocelot.Middleware
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
public HttpContext HttpContext { get; }
public DownstreamReRoute DownstreamReRoute { get; set; }
@ -32,6 +27,8 @@ namespace Ocelot.Middleware
public List<Error> Errors { get; }
public IInternalConfiguration Configuration { get; set; }
public bool IsError => Errors.Count > 0;
}
}

View File

@ -23,7 +23,7 @@ namespace Ocelot.Middleware.Multiplexer
var downstreamContext = new DownstreamContext(context.HttpContext)
{
TemplatePlaceholderNameAndValues = context.TemplatePlaceholderNameAndValues,
ServiceProviderConfiguration = context.ServiceProviderConfiguration,
Configuration = context.Configuration,
DownstreamReRoute = reRoute.DownstreamReRoute[i],
};

View File

@ -68,7 +68,7 @@ namespace Ocelot.Requester
handlers.Add(() => (DelegatingHandler)_factory.Get());
}
if (request.IsQos)
if (request.QosOptions.UseQos)
{
var qosProvider = _qosProviderHouse.Get(request);

View File

@ -58,9 +58,9 @@ namespace Ocelot.Requester
.LogWarning($"You have ignored all SSL warnings by using DangerousAcceptAnyServerCertificateValidator for this DownstreamReRoute, UpstreamPathTemplate: {context.DownstreamReRoute.UpstreamPathTemplate}, DownstreamPathTemplate: {context.DownstreamReRoute.DownstreamPathTemplate}");
}
var timeout = context.DownstreamReRoute.QosOptionsOptions.TimeoutValue == 0
var timeout = context.DownstreamReRoute.QosOptions.TimeoutValue == 0
? _defaultTimeout
: TimeSpan.FromMilliseconds(context.DownstreamReRoute.QosOptionsOptions.TimeoutValue);
: TimeSpan.FromMilliseconds(context.DownstreamReRoute.QosOptions.TimeoutValue);
_httpClient = new HttpClient(CreateHttpMessageHandler(httpclientHandler, context.DownstreamReRoute))
{

View File

@ -19,15 +19,15 @@ namespace Ocelot.Requester.QoS
{
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();
_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.TimeoutValue), reRoute.QosOptionsOptions.TimeoutStrategy);
_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptions.TimeoutValue), reRoute.QosOptions.TimeoutStrategy);
_circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.Or<TimeoutRejectedException>()
.Or<TimeoutException>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking,
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak),
exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking,
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptions.DurationOfBreak),
onBreak: (ex, breakDelay) =>
{
_logger.LogError(

View File

@ -14,7 +14,7 @@ namespace Ocelot.Requester.QoS
public IQoSProvider Get(DownstreamReRoute reRoute)
{
if (reRoute.IsQos)
if (reRoute.QosOptions.UseQos)
{
return new PollyQoSProvider(reRoute, _loggerFactory);
}

View File

@ -21,26 +21,26 @@ namespace Ocelot.Requester.QoS
{
try
{
if (_qoSProviders.TryGetValue(reRoute.QosKey, out var qosProvider))
if (_qoSProviders.TryGetValue(reRoute.QosOptions.Key, out var qosProvider))
{
if (reRoute.IsQos && qosProvider.CircuitBreaker == null)
if (reRoute.QosOptions.UseQos && qosProvider.CircuitBreaker == null)
{
qosProvider = _qoSProviderFactory.Get(reRoute);
Add(reRoute.QosKey, qosProvider);
Add(reRoute.QosOptions.Key, qosProvider);
}
return new OkResponse<IQoSProvider>(_qoSProviders[reRoute.QosKey]);
return new OkResponse<IQoSProvider>(_qoSProviders[reRoute.QosOptions.Key]);
}
qosProvider = _qoSProviderFactory.Get(reRoute);
Add(reRoute.QosKey, qosProvider);
Add(reRoute.QosOptions.Key, qosProvider);
return new OkResponse<IQoSProvider>(qosProvider);
}
catch (Exception ex)
{
return new ErrorResponse<IQoSProvider>(new List<Ocelot.Errors.Error>()
{
new UnableToFindQoSProviderError($"unabe to find qos provider for {reRoute.QosKey}, exception was {ex}")
new UnableToFindQoSProviderError($"unabe to find qos provider for {reRoute.QosOptions.Key}, exception was {ex}")
});
}
}

View File

@ -4,8 +4,8 @@ namespace Ocelot.ServiceDiscovery.Configuration
{
public ConsulRegistryConfiguration(string host, int port, string keyOfServiceInConsul, string token)
{
Host = host;
Port = port;
Host = string.IsNullOrEmpty(host) ? "localhost" : host;
Port = port > 0 ? port : 8500;
KeyOfServiceInConsul = keyOfServiceInConsul;
Token = token;
}

View File

@ -22,12 +22,7 @@ namespace Ocelot.ServiceDiscovery.Providers
{;
_logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
var consulHost = string.IsNullOrEmpty(config?.Host) ? "localhost" : config.Host;
var consulPort = config?.Port ?? 8500;
_config = new ConsulRegistryConfiguration(consulHost, consulPort, config?.KeyOfServiceInConsul, config?.Token);
_config = config;
_consul = clientFactory.Get(_config);
}