Feature/refactoring internal config creation stack (#600)

* tidy up some code so I can understand it

* broke al the things that make config out into their own classes etc..sigh

* fix the things i broked

* #597 test for issue, works on this branch :E

* #597 removed comments

* added tests for new load balancer creator..basic

* added tests for lb creator and aggregates creator

* added tests for config creator

* boiler plate for tests

* added dynamics tests

* wip

* finished refactoring for now
This commit is contained in:
Tom Pallister
2018-09-11 21:41:58 +01:00
committed by GitHub
parent b491bd50a8
commit 44f8e312a8
34 changed files with 2086 additions and 2012 deletions

View File

@ -33,7 +33,6 @@ namespace Ocelot.Configuration.Builder
private List<HeaderFindAndReplace> _upstreamHeaderFindAndReplace;
private List<HeaderFindAndReplace> _downstreamHeaderFindAndReplace;
private readonly List<DownstreamHostAndPort> _downstreamAddresses;
private string _upstreamHost;
private string _key;
private List<string> _delegatingHandlers;
private List<AddHeader> _addHeadersToDownstream;
@ -54,12 +53,6 @@ namespace Ocelot.Configuration.Builder
return this;
}
public DownstreamReRouteBuilder WithUpstreamHost(string upstreamAddresses)
{
_upstreamHost = upstreamAddresses;
return this;
}
public DownstreamReRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions)
{
_loadBalancerOptions = loadBalancerOptions;

View File

@ -1,39 +1,46 @@
namespace Ocelot.Configuration.Builder
{
public class ReRouteOptionsBuilder
{
private bool _isAuthenticated;
private bool _isAuthorised;
private bool _isCached;
private bool _enableRateLimiting;
public ReRouteOptionsBuilder WithIsCached(bool isCached)
{
_isCached = isCached;
return this;
}
public ReRouteOptionsBuilder WithIsAuthenticated(bool isAuthenticated)
{
_isAuthenticated = isAuthenticated;
return this;
}
public ReRouteOptionsBuilder WithIsAuthorised(bool isAuthorised)
{
_isAuthorised = isAuthorised;
return this;
}
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
{
_enableRateLimiting = enableRateLimiting;
return this;
}
public ReRouteOptions Build()
{
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting);
}
}
}
namespace Ocelot.Configuration.Builder
{
public class ReRouteOptionsBuilder
{
private bool _isAuthenticated;
private bool _isAuthorised;
private bool _isCached;
private bool _enableRateLimiting;
private bool _useServiceDiscovery;
public ReRouteOptionsBuilder WithIsCached(bool isCached)
{
_isCached = isCached;
return this;
}
public ReRouteOptionsBuilder WithIsAuthenticated(bool isAuthenticated)
{
_isAuthenticated = isAuthenticated;
return this;
}
public ReRouteOptionsBuilder WithIsAuthorised(bool isAuthorised)
{
_isAuthorised = isAuthorised;
return this;
}
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
{
_enableRateLimiting = enableRateLimiting;
return this;
}
public ReRouteOptionsBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
{
_useServiceDiscovery = useServiceDiscovery;
return this;
}
public ReRouteOptions Build()
{
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting, _useServiceDiscovery);
}
}
}

View File

@ -0,0 +1,50 @@
namespace Ocelot.Configuration.Creator
{
using System.Collections.Generic;
using System.Linq;
using Builder;
using File;
public class AggregatesCreator : IAggregatesCreator
{
private readonly IUpstreamTemplatePatternCreator _creator;
public AggregatesCreator(IUpstreamTemplatePatternCreator creator)
{
_creator = creator;
}
public List<ReRoute> Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes)
{
return fileConfiguration.Aggregates
.Select(aggregate => SetUpAggregateReRoute(reRoutes, aggregate, fileConfiguration.GlobalConfiguration))
.Where(aggregate => aggregate != null)
.ToList();
}
private ReRoute SetUpAggregateReRoute(IEnumerable<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration)
{
var applicableReRoutes = reRoutes
.SelectMany(x => x.DownstreamReRoute)
.Where(r => aggregateReRoute.ReRouteKeys.Contains(r.Key))
.ToList();
if (applicableReRoutes.Count != aggregateReRoute.ReRouteKeys.Count)
{
return null;
}
var upstreamTemplatePattern = _creator.Create(aggregateReRoute);
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(aggregateReRoute.UpstreamHttpMethod)
.WithUpstreamPathTemplate(upstreamTemplatePattern)
.WithDownstreamReRoutes(applicableReRoutes)
.WithUpstreamHost(aggregateReRoute.UpstreamHost)
.WithAggregator(aggregateReRoute.Aggregator)
.Build();
return reRoute;
}
}
}

View File

@ -0,0 +1,55 @@
namespace Ocelot.Configuration.Creator
{
using System;
using System.Collections.Generic;
using File;
using DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
public class ConfigurationCreator : IConfigurationCreator
{
private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
private readonly IQoSOptionsCreator _qosOptionsCreator;
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
private readonly IAdministrationPath _adminPath;
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
public ConfigurationCreator(
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
IQoSOptionsCreator qosOptionsCreator,
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
IServiceProvider serviceProvider,
ILoadBalancerOptionsCreator loadBalancerOptionsCreator
)
{
_adminPath = serviceProvider.GetService<IAdministrationPath>();
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
_serviceProviderConfigCreator = serviceProviderConfigCreator;
_qosOptionsCreator = qosOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
}
public InternalConfiguration Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes)
{
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
var lbOptions = _loadBalancerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);
var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);
var adminPath = _adminPath != null ? _adminPath.Path : null;
return new InternalConfiguration(reRoutes,
adminPath,
serviceProviderConfiguration,
fileConfiguration.GlobalConfiguration.RequestIdKey,
lbOptions,
fileConfiguration.GlobalConfiguration.DownstreamScheme,
qosOptions,
httpHandlerOptions
);
}
}
}

View File

@ -0,0 +1,42 @@
namespace Ocelot.Configuration.Creator
{
using System.Collections.Generic;
using System.Linq;
using Builder;
using File;
public class DynamicsCreator : IDynamicsCreator
{
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
public DynamicsCreator(IRateLimitOptionsCreator rateLimitOptionsCreator)
{
_rateLimitOptionsCreator = rateLimitOptionsCreator;
}
public List<ReRoute> Create(FileConfiguration fileConfiguration)
{
return fileConfiguration.DynamicReRoutes
.Select(dynamic => SetUpDynamicReRoute(dynamic, fileConfiguration.GlobalConfiguration))
.ToList();
}
private ReRoute SetUpDynamicReRoute(FileDynamicReRoute fileDynamicReRoute, FileGlobalConfiguration globalConfiguration)
{
var rateLimitOption = _rateLimitOptionsCreator
.Create(fileDynamicReRoute.RateLimitRule, globalConfiguration);
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithEnableRateLimiting(rateLimitOption.EnableRateLimiting)
.WithRateLimitOptions(rateLimitOption)
.WithServiceName(fileDynamicReRoute.ServiceName)
.Build();
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoute(downstreamReRoute)
.Build();
return reRoute;
}
}
}

View File

@ -1,84 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Ocelot.Cache;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Validator;
using Ocelot.DependencyInjection;
using Ocelot.Logging;
using Ocelot.Responses;
using Microsoft.Extensions.DependencyInjection;
namespace Ocelot.Configuration.Creator
{
using LoadBalancer.LoadBalancers;
using System.Linq;
using System.Threading.Tasks;
using File;
using Validator;
using Responses;
/// <summary>
/// Register as singleton
/// </summary>
public class FileInternalConfigurationCreator : IInternalConfigurationCreator
{
private readonly IConfigurationValidator _configurationValidator;
private readonly IOcelotLogger _logger;
private readonly IClaimsToThingCreator _claimsToThingCreator;
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
private readonly IRequestIdKeyCreator _requestIdKeyCreator;
private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
private readonly IQoSOptionsCreator _qosOptionsCreator;
private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
private readonly IRegionCreator _regionCreator;
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
private readonly IAdministrationPath _adminPath;
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
private readonly IConfigurationCreator _configCreator;
private readonly IDynamicsCreator _dynamicsCreator;
private readonly IReRoutesCreator _reRoutesCreator;
private readonly IAggregatesCreator _aggregatesCreator;
public FileInternalConfigurationCreator(
IConfigurationValidator configurationValidator,
IOcelotLoggerFactory loggerFactory,
IClaimsToThingCreator claimsToThingCreator,
IAuthenticationOptionsCreator authOptionsCreator,
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
IRequestIdKeyCreator requestIdKeyCreator,
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
IQoSOptionsCreator qosOptionsCreator,
IReRouteOptionsCreator fileReRouteOptionsCreator,
IRateLimitOptionsCreator rateLimitOptionsCreator,
IRegionCreator regionCreator,
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
IServiceProvider serviceProvider,
IHeaderFindAndReplaceCreator headerFAndRCreator,
IDownstreamAddressesCreator downstreamAddressesCreator
IReRoutesCreator reRoutesCreator,
IAggregatesCreator aggregatesCreator,
IDynamicsCreator dynamicsCreator,
IConfigurationCreator configCreator
)
{
_downstreamAddressesCreator = downstreamAddressesCreator;
_headerFAndRCreator = headerFAndRCreator;
_adminPath = serviceProvider.GetService<IAdministrationPath>();
_regionCreator = regionCreator;
_rateLimitOptionsCreator = rateLimitOptionsCreator;
_requestIdKeyCreator = requestIdKeyCreator;
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
_authOptionsCreator = authOptionsCreator;
_configCreator = configCreator;
_dynamicsCreator = dynamicsCreator;
_aggregatesCreator = aggregatesCreator;
_reRoutesCreator = reRoutesCreator;
_configurationValidator = configurationValidator;
_logger = loggerFactory.CreateLogger<FileInternalConfigurationCreator>();
_claimsToThingCreator = claimsToThingCreator;
_serviceProviderConfigCreator = serviceProviderConfigCreator;
_qosOptionsCreator = qosOptionsCreator;
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
}
public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
{
var config = await SetUpConfiguration(fileConfiguration);
return config;
}
private async Task<Response<IInternalConfiguration>> SetUpConfiguration(FileConfiguration fileConfiguration)
public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
{
var response = await _configurationValidator.IsValid(fileConfiguration);
@ -87,197 +38,20 @@ namespace Ocelot.Configuration.Creator
return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
}
var reRoutes = new List<ReRoute>();
var reRoutes = _reRoutesCreator.Create(fileConfiguration);
foreach (var reRoute in fileConfiguration.ReRoutes)
{
var downstreamReRoute = SetUpDownstreamReRoute(reRoute, fileConfiguration.GlobalConfiguration);
var aggregates = _aggregatesCreator.Create(fileConfiguration, reRoutes);
var ocelotReRoute = SetUpReRoute(reRoute, downstreamReRoute);
reRoutes.Add(ocelotReRoute);
}
var dynamicReRoute = _dynamicsCreator.Create(fileConfiguration);
foreach (var aggregate in fileConfiguration.Aggregates)
{
var ocelotReRoute = SetUpAggregateReRoute(reRoutes, aggregate, fileConfiguration.GlobalConfiguration);
reRoutes.Add(ocelotReRoute);
}
var mergedReRoutes = reRoutes
.Union(aggregates)
.Union(dynamicReRoute)
.ToList();
foreach(var fileDynamicReRoute in fileConfiguration.DynamicReRoutes)
{
var reRoute = SetUpDynamicReRoute(fileDynamicReRoute, fileConfiguration.GlobalConfiguration);
reRoutes.Add(reRoute);
}
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
var lbOptions = CreateLoadBalancerOptions(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);
var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);
var adminPath = _adminPath != null ? _adminPath.Path : null;
var config = new InternalConfiguration(reRoutes,
adminPath,
serviceProviderConfiguration,
fileConfiguration.GlobalConfiguration.RequestIdKey,
lbOptions,
fileConfiguration.GlobalConfiguration.DownstreamScheme,
qosOptions,
httpHandlerOptions
);
var config = _configCreator.Create(fileConfiguration, mergedReRoutes);
return new OkResponse<IInternalConfiguration>(config);
}
private ReRoute SetUpDynamicReRoute(FileDynamicReRoute fileDynamicReRoute, FileGlobalConfiguration globalConfiguration)
{
var rateLimitOption = _rateLimitOptionsCreator.Create(fileDynamicReRoute.RateLimitRule, globalConfiguration);
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithEnableRateLimiting(true)
.WithRateLimitOptions(rateLimitOption)
.WithServiceName(fileDynamicReRoute.ServiceName)
.Build();
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoute(downstreamReRoute)
.Build();
return reRoute;
}
private ReRoute SetUpAggregateReRoute(List<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration)
{
var applicableReRoutes = reRoutes
.SelectMany(x => x.DownstreamReRoute)
.Where(r => aggregateReRoute.ReRouteKeys.Contains(r.Key))
.ToList();
if(applicableReRoutes.Count != aggregateReRoute.ReRouteKeys.Count)
{
//todo - log or throw or return error whatever?
}
//make another re route out of these
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(aggregateReRoute);
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(aggregateReRoute.UpstreamHttpMethod)
.WithUpstreamPathTemplate(upstreamTemplatePattern)
.WithDownstreamReRoutes(applicableReRoutes)
.WithUpstreamHost(aggregateReRoute.UpstreamHost)
.WithAggregator(aggregateReRoute.Aggregator)
.Build();
return reRoute;
}
private ReRoute SetUpReRoute(FileReRoute fileReRoute, DownstreamReRoute downstreamReRoutes)
{
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
.WithUpstreamPathTemplate(upstreamTemplatePattern)
.WithDownstreamReRoute(downstreamReRoutes)
.WithUpstreamHost(fileReRoute.UpstreamHost)
.Build();
return reRoute;
}
private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
{
var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute);
var requestIdKey = _requestIdKeyCreator.Create(fileReRoute, globalConfiguration);
var reRouteKey = CreateReRouteKey(fileReRoute);
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
var qosOptions = _qosOptionsCreator.Create(fileReRoute.QoSOptions, fileReRoute.UpstreamPathTemplate, fileReRoute.UpstreamHttpMethod.ToArray());
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute.RateLimitOptions, globalConfiguration);
var region = _regionCreator.Create(fileReRoute);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute.HttpHandlerOptions);
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
var lbOptions = CreateLoadBalancerOptions(fileReRoute.LoadBalancerOptions);
var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName);
var reRoute = new DownstreamReRouteBuilder()
.WithKey(fileReRoute.Key)
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
.WithUpstreamPathTemplate(upstreamTemplatePattern)
.WithIsAuthenticated(fileReRouteOptions.IsAuthenticated)
.WithAuthenticationOptions(authOptionsForRoute)
.WithClaimsToHeaders(claimsToHeaders)
.WithClaimsToClaims(claimsToClaims)
.WithRouteClaimsRequirement(fileReRoute.RouteClaimsRequirement)
.WithIsAuthorised(fileReRouteOptions.IsAuthorised)
.WithClaimsToQueries(claimsToQueries)
.WithRequestIdKey(requestIdKey)
.WithIsCached(fileReRouteOptions.IsCached)
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
.WithLoadBalancerOptions(lbOptions)
.WithDownstreamAddresses(downstreamAddresses)
.WithLoadBalancerKey(reRouteKey)
.WithQosOptions(qosOptions)
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
.WithRateLimitOptions(rateLimitOption)
.WithHttpHandlerOptions(httpHandlerOptions)
.WithServiceName(fileReRoute.ServiceName)
.WithUseServiceDiscovery(useServiceDiscovery)
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
.WithUpstreamHost(fileReRoute.UpstreamHost)
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
.WithDangerousAcceptAnyServerCertificateValidator(fileReRoute.DangerousAcceptAnyServerCertificateValidator)
.Build();
return reRoute;
}
private LoadBalancerOptions CreateLoadBalancerOptions(FileLoadBalancerOptions options)
{
return new LoadBalancerOptionsBuilder()
.WithType(options.Type)
.WithKey(options.Key)
.WithExpiryInMs(options.Expiry)
.Build();
}
private string CreateReRouteKey(FileReRoute fileReRoute)
{
if (!string.IsNullOrEmpty(fileReRoute.LoadBalancerOptions.Type) && !string.IsNullOrEmpty(fileReRoute.LoadBalancerOptions.Key) && fileReRoute.LoadBalancerOptions.Type == nameof(CookieStickySessions))
{
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
}
return $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}|{string.Join(",", fileReRoute.DownstreamHostAndPorts.Select(x => $"{x.Host}:{x.Port}"))}";
}
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IAggregatesCreator
{
List<ReRoute> Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes);
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IConfigurationCreator
{
InternalConfiguration Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes);
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IDynamicsCreator
{
List<ReRoute> Create(FileConfiguration fileConfiguration);
}
}

View File

@ -0,0 +1,9 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface ILoadBalancerOptionsCreator
{
LoadBalancerOptions Create(FileLoadBalancerOptions options);
}
}

View File

@ -1,11 +1,12 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IQoSOptionsCreator
{
QoSOptions Create(FileQoSOptions options);
QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods);
QoSOptions Create(QoSOptions options, string pathTemplate, string[] httpMethods);
}
}
using System.Collections.Generic;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IQoSOptionsCreator
{
QoSOptions Create(FileQoSOptions options);
QoSOptions Create(FileQoSOptions options, string pathTemplate, List<string> httpMethods);
QoSOptions Create(QoSOptions options, string pathTemplate, List<string> httpMethods);
}
}

View File

@ -0,0 +1,9 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IReRouteKeyCreator
{
string Create(FileReRoute fileReRoute);
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IReRoutesCreator
{
List<ReRoute> Create(FileConfiguration fileConfiguration);
}
}

View File

@ -0,0 +1,17 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public class LoadBalancerOptionsCreator : ILoadBalancerOptionsCreator
{
public LoadBalancerOptions Create(FileLoadBalancerOptions options)
{
return new LoadBalancerOptionsBuilder()
.WithType(options.Type)
.WithKey(options.Key)
.WithExpiryInMs(options.Expiry)
.Build();
}
}
}

View File

@ -1,47 +1,48 @@
namespace Ocelot.Configuration.Creator
{
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using System.Linq;
public class QoSOptionsCreator : IQoSOptionsCreator
{
public QoSOptions Create(FileQoSOptions options)
{
return new QoSOptionsBuilder()
.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)}";
}
}
}
namespace Ocelot.Configuration.Creator
{
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using System.Collections.Generic;
using System.Linq;
public class QoSOptionsCreator : IQoSOptionsCreator
{
public QoSOptions Create(FileQoSOptions options)
{
return new QoSOptionsBuilder()
.WithExceptionsAllowedBeforeBreaking(options.ExceptionsAllowedBeforeBreaking)
.WithDurationOfBreak(options.DurationOfBreak)
.WithTimeoutValue(options.TimeoutValue)
.Build();
}
public QoSOptions Create(FileQoSOptions options, string pathTemplate, List<string> httpMethods)
{
var key = CreateKey(pathTemplate, httpMethods);
return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking);
}
public QoSOptions Create(QoSOptions options, string pathTemplate, List<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, List<string> httpMethods)
{
return $"{pathTemplate.FirstOrDefault()}|{string.Join(",", httpMethods)}";
}
}
}

View File

@ -1,5 +1,4 @@
using System;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
@ -8,11 +7,9 @@ namespace Ocelot.Configuration.Creator
{
public RateLimitOptions Create(FileRateLimitRule fileRateLimitRule, FileGlobalConfiguration globalConfiguration)
{
RateLimitOptions rateLimitOption = null;
if (fileRateLimitRule != null && fileRateLimitRule.EnableRateLimiting)
{
rateLimitOption = new RateLimitOptionsBuilder()
return new RateLimitOptionsBuilder()
.WithClientIdHeader(globalConfiguration.RateLimitOptions.ClientIdHeader)
.WithClientWhiteList(fileRateLimitRule.ClientWhitelist)
.WithDisableRateLimitHeaders(globalConfiguration.RateLimitOptions.DisableRateLimitHeaders)
@ -26,7 +23,7 @@ namespace Ocelot.Configuration.Creator
.Build();
}
return rateLimitOption;
return new RateLimitOptionsBuilder().WithEnableRateLimiting(false).Build();
}
}
}

View File

@ -0,0 +1,31 @@
using System.Linq;
using Ocelot.Configuration.File;
using Ocelot.LoadBalancer.LoadBalancers;
namespace Ocelot.Configuration.Creator
{
public class ReRouteKeyCreator : IReRouteKeyCreator
{
public string Create(FileReRoute fileReRoute)
{
if (IsStickySession(fileReRoute))
{
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
}
return $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}|{string.Join(",", fileReRoute.DownstreamHostAndPorts.Select(x => $"{x.Host}:{x.Port}"))}";
}
private bool IsStickySession(FileReRoute fileReRoute)
{
if (!string.IsNullOrEmpty(fileReRoute.LoadBalancerOptions.Type)
&& !string.IsNullOrEmpty(fileReRoute.LoadBalancerOptions.Key)
&& fileReRoute.LoadBalancerOptions.Type == nameof(CookieStickySessions))
{
return true;
}
return false;
}
}
}

View File

@ -11,12 +11,14 @@ namespace Ocelot.Configuration.Creator
var isAuthorised = IsAuthorised(fileReRoute);
var isCached = IsCached(fileReRoute);
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName);
var options = new ReRouteOptionsBuilder()
.WithIsAuthenticated(isAuthenticated)
.WithIsAuthorised(isAuthorised)
.WithIsCached(isCached)
.WithRateLimiting(enableRateLimiting)
.WithUseServiceDiscovery(useServiceDiscovery)
.Build();
return options;

View File

@ -0,0 +1,150 @@
namespace Ocelot.Configuration.Creator
{
using System.Collections.Generic;
using System.Linq;
using Cache;
using Builder;
using File;
public class ReRoutesCreator : IReRoutesCreator
{
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
private readonly IClaimsToThingCreator _claimsToThingCreator;
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
private readonly IRequestIdKeyCreator _requestIdKeyCreator;
private readonly IQoSOptionsCreator _qosOptionsCreator;
private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
private readonly IRegionCreator _regionCreator;
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
private readonly IReRouteKeyCreator _reRouteKeyCreator;
public ReRoutesCreator(
IClaimsToThingCreator claimsToThingCreator,
IAuthenticationOptionsCreator authOptionsCreator,
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
IRequestIdKeyCreator requestIdKeyCreator,
IQoSOptionsCreator qosOptionsCreator,
IReRouteOptionsCreator fileReRouteOptionsCreator,
IRateLimitOptionsCreator rateLimitOptionsCreator,
IRegionCreator regionCreator,
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
IHeaderFindAndReplaceCreator headerFAndRCreator,
IDownstreamAddressesCreator downstreamAddressesCreator,
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
IReRouteKeyCreator reRouteKeyCreator
)
{
_reRouteKeyCreator = reRouteKeyCreator;
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
_downstreamAddressesCreator = downstreamAddressesCreator;
_headerFAndRCreator = headerFAndRCreator;
_regionCreator = regionCreator;
_rateLimitOptionsCreator = rateLimitOptionsCreator;
_requestIdKeyCreator = requestIdKeyCreator;
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
_authOptionsCreator = authOptionsCreator;
_claimsToThingCreator = claimsToThingCreator;
_qosOptionsCreator = qosOptionsCreator;
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
}
public List<ReRoute> Create(FileConfiguration fileConfiguration)
{
return fileConfiguration.ReRoutes
.Select(reRoute =>
{
var downstreamReRoute = SetUpDownstreamReRoute(reRoute, fileConfiguration.GlobalConfiguration);
return SetUpReRoute(reRoute, downstreamReRoute);
})
.ToList();
}
private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
{
var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute);
var requestIdKey = _requestIdKeyCreator.Create(fileReRoute, globalConfiguration);
var reRouteKey = _reRouteKeyCreator.Create(fileReRoute);
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
var qosOptions = _qosOptionsCreator.Create(fileReRoute.QoSOptions, fileReRoute.UpstreamPathTemplate, fileReRoute.UpstreamHttpMethod);
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute.RateLimitOptions, globalConfiguration);
var region = _regionCreator.Create(fileReRoute);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute.HttpHandlerOptions);
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
var lbOptions = _loadBalancerOptionsCreator.Create(fileReRoute.LoadBalancerOptions);
var reRoute = new DownstreamReRouteBuilder()
.WithKey(fileReRoute.Key)
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
.WithUpstreamPathTemplate(upstreamTemplatePattern)
.WithIsAuthenticated(fileReRouteOptions.IsAuthenticated)
.WithAuthenticationOptions(authOptionsForRoute)
.WithClaimsToHeaders(claimsToHeaders)
.WithClaimsToClaims(claimsToClaims)
.WithRouteClaimsRequirement(fileReRoute.RouteClaimsRequirement)
.WithIsAuthorised(fileReRouteOptions.IsAuthorised)
.WithClaimsToQueries(claimsToQueries)
.WithRequestIdKey(requestIdKey)
.WithIsCached(fileReRouteOptions.IsCached)
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
.WithLoadBalancerOptions(lbOptions)
.WithDownstreamAddresses(downstreamAddresses)
.WithLoadBalancerKey(reRouteKey)
.WithQosOptions(qosOptions)
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
.WithRateLimitOptions(rateLimitOption)
.WithHttpHandlerOptions(httpHandlerOptions)
.WithServiceName(fileReRoute.ServiceName)
.WithUseServiceDiscovery(fileReRouteOptions.UseServiceDiscovery)
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
.WithDangerousAcceptAnyServerCertificateValidator(fileReRoute.DangerousAcceptAnyServerCertificateValidator)
.Build();
return reRoute;
}
private ReRoute SetUpReRoute(FileReRoute fileReRoute, DownstreamReRoute downstreamReRoutes)
{
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
.WithUpstreamPathTemplate(upstreamTemplatePattern)
.WithDownstreamReRoute(downstreamReRoutes)
.WithUpstreamHost(fileReRoute.UpstreamHost)
.Build();
return reRoute;
}
}
}

View File

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

View File

@ -56,6 +56,12 @@ namespace Ocelot.DependencyInjection
Services.TryAddSingleton<IInternalConfigurationRepository, InMemoryInternalConfigurationRepository>();
Services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>();
Services.AddSingleton<HostAndPortValidator>();
Services.AddSingleton<IReRoutesCreator, ReRoutesCreator>();
Services.AddSingleton<IAggregatesCreator, AggregatesCreator>();
Services.AddSingleton<IReRouteKeyCreator, ReRouteKeyCreator>();
Services.AddSingleton<IConfigurationCreator, ConfigurationCreator>();
Services.AddSingleton<IDynamicsCreator, DynamicsCreator>();
Services.AddSingleton<ILoadBalancerOptionsCreator, LoadBalancerOptionsCreator>();
Services.AddSingleton<ReRouteFluentValidator>();
Services.AddSingleton<FileGlobalConfigurationFluentValidator>();
Services.AddSingleton<FileQoSOptionsFluentValidator>();

View File

@ -42,7 +42,7 @@
return downstreamRoute;
}
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new []{ upstreamHttpMethod });
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new List<string> { upstreamHttpMethod });
var upstreamPathTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue(upstreamUrlPath).Build();