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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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> _upstreamHeaderFindAndReplace;
private List<HeaderFindAndReplace> _downstreamHeaderFindAndReplace; private List<HeaderFindAndReplace> _downstreamHeaderFindAndReplace;
private readonly List<DownstreamHostAndPort> _downstreamAddresses; private readonly List<DownstreamHostAndPort> _downstreamAddresses;
private string _upstreamHost;
private string _key; private string _key;
private List<string> _delegatingHandlers; private List<string> _delegatingHandlers;
private List<AddHeader> _addHeadersToDownstream; private List<AddHeader> _addHeadersToDownstream;
@ -54,12 +53,6 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public DownstreamReRouteBuilder WithUpstreamHost(string upstreamAddresses)
{
_upstreamHost = upstreamAddresses;
return this;
}
public DownstreamReRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions) public DownstreamReRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions)
{ {
_loadBalancerOptions = loadBalancerOptions; _loadBalancerOptions = loadBalancerOptions;

View File

@ -6,6 +6,7 @@ namespace Ocelot.Configuration.Builder
private bool _isAuthorised; private bool _isAuthorised;
private bool _isCached; private bool _isCached;
private bool _enableRateLimiting; private bool _enableRateLimiting;
private bool _useServiceDiscovery;
public ReRouteOptionsBuilder WithIsCached(bool isCached) public ReRouteOptionsBuilder WithIsCached(bool isCached)
{ {
@ -31,9 +32,15 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ReRouteOptionsBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
{
_useServiceDiscovery = useServiceDiscovery;
return this;
}
public ReRouteOptions Build() public ReRouteOptions Build()
{ {
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting); 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 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 public class FileInternalConfigurationCreator : IInternalConfigurationCreator
{ {
private readonly IConfigurationValidator _configurationValidator; private readonly IConfigurationValidator _configurationValidator;
private readonly IOcelotLogger _logger; private readonly IConfigurationCreator _configCreator;
private readonly IClaimsToThingCreator _claimsToThingCreator; private readonly IDynamicsCreator _dynamicsCreator;
private readonly IAuthenticationOptionsCreator _authOptionsCreator; private readonly IReRoutesCreator _reRoutesCreator;
private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator; private readonly IAggregatesCreator _aggregatesCreator;
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;
public FileInternalConfigurationCreator( public FileInternalConfigurationCreator(
IConfigurationValidator configurationValidator, IConfigurationValidator configurationValidator,
IOcelotLoggerFactory loggerFactory, IReRoutesCreator reRoutesCreator,
IClaimsToThingCreator claimsToThingCreator, IAggregatesCreator aggregatesCreator,
IAuthenticationOptionsCreator authOptionsCreator, IDynamicsCreator dynamicsCreator,
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator, IConfigurationCreator configCreator
IRequestIdKeyCreator requestIdKeyCreator,
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
IQoSOptionsCreator qosOptionsCreator,
IReRouteOptionsCreator fileReRouteOptionsCreator,
IRateLimitOptionsCreator rateLimitOptionsCreator,
IRegionCreator regionCreator,
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
IServiceProvider serviceProvider,
IHeaderFindAndReplaceCreator headerFAndRCreator,
IDownstreamAddressesCreator downstreamAddressesCreator
) )
{ {
_downstreamAddressesCreator = downstreamAddressesCreator; _configCreator = configCreator;
_headerFAndRCreator = headerFAndRCreator; _dynamicsCreator = dynamicsCreator;
_adminPath = serviceProvider.GetService<IAdministrationPath>(); _aggregatesCreator = aggregatesCreator;
_regionCreator = regionCreator; _reRoutesCreator = reRoutesCreator;
_rateLimitOptionsCreator = rateLimitOptionsCreator;
_requestIdKeyCreator = requestIdKeyCreator;
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
_authOptionsCreator = authOptionsCreator;
_configurationValidator = configurationValidator; _configurationValidator = configurationValidator;
_logger = loggerFactory.CreateLogger<FileInternalConfigurationCreator>();
_claimsToThingCreator = claimsToThingCreator;
_serviceProviderConfigCreator = serviceProviderConfigCreator;
_qosOptionsCreator = qosOptionsCreator;
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
} }
public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration) public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
{
var config = await SetUpConfiguration(fileConfiguration);
return config;
}
private async Task<Response<IInternalConfiguration>> SetUpConfiguration(FileConfiguration fileConfiguration)
{ {
var response = await _configurationValidator.IsValid(fileConfiguration); var response = await _configurationValidator.IsValid(fileConfiguration);
@ -87,197 +38,20 @@ namespace Ocelot.Configuration.Creator
return new ErrorResponse<IInternalConfiguration>(response.Data.Errors); return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
} }
var reRoutes = new List<ReRoute>(); var reRoutes = _reRoutesCreator.Create(fileConfiguration);
foreach (var reRoute in fileConfiguration.ReRoutes) var aggregates = _aggregatesCreator.Create(fileConfiguration, reRoutes);
{
var downstreamReRoute = SetUpDownstreamReRoute(reRoute, fileConfiguration.GlobalConfiguration);
var ocelotReRoute = SetUpReRoute(reRoute, downstreamReRoute); var dynamicReRoute = _dynamicsCreator.Create(fileConfiguration);
reRoutes.Add(ocelotReRoute); var mergedReRoutes = reRoutes
} .Union(aggregates)
.Union(dynamicReRoute)
.ToList();
foreach (var aggregate in fileConfiguration.Aggregates) var config = _configCreator.Create(fileConfiguration, mergedReRoutes);
{
var ocelotReRoute = SetUpAggregateReRoute(reRoutes, aggregate, fileConfiguration.GlobalConfiguration);
reRoutes.Add(ocelotReRoute);
}
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
);
return new OkResponse<IInternalConfiguration>(config); 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,3 +1,4 @@
using System.Collections.Generic;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator namespace Ocelot.Configuration.Creator
@ -5,7 +6,7 @@ namespace Ocelot.Configuration.Creator
public interface IQoSOptionsCreator public interface IQoSOptionsCreator
{ {
QoSOptions Create(FileQoSOptions options); QoSOptions Create(FileQoSOptions options);
QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods); QoSOptions Create(FileQoSOptions options, string pathTemplate, List<string> httpMethods);
QoSOptions Create(QoSOptions options, string pathTemplate, 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

@ -2,6 +2,7 @@ namespace Ocelot.Configuration.Creator
{ {
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using System.Collections.Generic;
using System.Linq; using System.Linq;
public class QoSOptionsCreator : IQoSOptionsCreator public class QoSOptionsCreator : IQoSOptionsCreator
@ -15,14 +16,14 @@ namespace Ocelot.Configuration.Creator
.Build(); .Build();
} }
public QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods) public QoSOptions Create(FileQoSOptions options, string pathTemplate, List<string> httpMethods)
{ {
var key = CreateKey(pathTemplate, httpMethods); var key = CreateKey(pathTemplate, httpMethods);
return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking); return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking);
} }
public QoSOptions Create(QoSOptions options, string pathTemplate, string[] httpMethods) public QoSOptions Create(QoSOptions options, string pathTemplate, List<string> httpMethods)
{ {
var key = CreateKey(pathTemplate, httpMethods); var key = CreateKey(pathTemplate, httpMethods);
@ -39,7 +40,7 @@ namespace Ocelot.Configuration.Creator
.Build(); .Build();
} }
private string CreateKey(string pathTemplate, string[] httpMethods) private string CreateKey(string pathTemplate, List<string> httpMethods)
{ {
return $"{pathTemplate.FirstOrDefault()}|{string.Join(",", 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; using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator namespace Ocelot.Configuration.Creator
@ -8,11 +7,9 @@ namespace Ocelot.Configuration.Creator
{ {
public RateLimitOptions Create(FileRateLimitRule fileRateLimitRule, FileGlobalConfiguration globalConfiguration) public RateLimitOptions Create(FileRateLimitRule fileRateLimitRule, FileGlobalConfiguration globalConfiguration)
{ {
RateLimitOptions rateLimitOption = null;
if (fileRateLimitRule != null && fileRateLimitRule.EnableRateLimiting) if (fileRateLimitRule != null && fileRateLimitRule.EnableRateLimiting)
{ {
rateLimitOption = new RateLimitOptionsBuilder() return new RateLimitOptionsBuilder()
.WithClientIdHeader(globalConfiguration.RateLimitOptions.ClientIdHeader) .WithClientIdHeader(globalConfiguration.RateLimitOptions.ClientIdHeader)
.WithClientWhiteList(fileRateLimitRule.ClientWhitelist) .WithClientWhiteList(fileRateLimitRule.ClientWhitelist)
.WithDisableRateLimitHeaders(globalConfiguration.RateLimitOptions.DisableRateLimitHeaders) .WithDisableRateLimitHeaders(globalConfiguration.RateLimitOptions.DisableRateLimitHeaders)
@ -26,7 +23,7 @@ namespace Ocelot.Configuration.Creator
.Build(); .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 isAuthorised = IsAuthorised(fileReRoute);
var isCached = IsCached(fileReRoute); var isCached = IsCached(fileReRoute);
var enableRateLimiting = IsEnableRateLimiting(fileReRoute); var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName);
var options = new ReRouteOptionsBuilder() var options = new ReRouteOptionsBuilder()
.WithIsAuthenticated(isAuthenticated) .WithIsAuthenticated(isAuthenticated)
.WithIsAuthorised(isAuthorised) .WithIsAuthorised(isAuthorised)
.WithIsCached(isCached) .WithIsCached(isCached)
.WithRateLimiting(enableRateLimiting) .WithRateLimiting(enableRateLimiting)
.WithUseServiceDiscovery(useServiceDiscovery)
.Build(); .Build();
return options; 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 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; IsAuthenticated = isAuthenticated;
IsAuthorised = isAuthorised; IsAuthorised = isAuthorised;
IsCached = isCached; IsCached = isCached;
EnableRateLimiting = isEnableRateLimiting; EnableRateLimiting = isEnableRateLimiting;
UseServiceDiscovery = useServiceDiscovery;
} }
public bool IsAuthenticated { get; private set; } public bool IsAuthenticated { get; private set; }
public bool IsAuthorised { get; private set; } public bool IsAuthorised { get; private set; }
public bool IsCached { get; private set; } public bool IsCached { get; private set; }
public bool EnableRateLimiting { 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<IInternalConfigurationRepository, InMemoryInternalConfigurationRepository>();
Services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>(); Services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>();
Services.AddSingleton<HostAndPortValidator>(); 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<ReRouteFluentValidator>();
Services.AddSingleton<FileGlobalConfigurationFluentValidator>(); Services.AddSingleton<FileGlobalConfigurationFluentValidator>();
Services.AddSingleton<FileQoSOptionsFluentValidator>(); Services.AddSingleton<FileQoSOptionsFluentValidator>();

View File

@ -42,7 +42,7 @@
return downstreamRoute; 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(); var upstreamPathTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue(upstreamUrlPath).Build();

View File

@ -31,6 +31,116 @@ namespace Ocelot.AcceptanceTests
_steps = new Steps(); _steps = new Steps();
} }
[Fact]
public void should_fix_issue_597()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/api/values?MailId={userid}",
UpstreamPathTemplate = "/key1data/{userid}",
UpstreamHttpMethod = new List<string> {"Get"},
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 8571
}
},
Key = "key1"
},
new FileReRoute
{
DownstreamPathTemplate = "/api/values?MailId={userid}",
UpstreamPathTemplate = "/key2data/{userid}",
UpstreamHttpMethod = new List<string> {"Get"},
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 8571
}
},
Key = "key2"
},
new FileReRoute
{
DownstreamPathTemplate = "/api/values?MailId={userid}",
UpstreamPathTemplate = "/key3data/{userid}",
UpstreamHttpMethod = new List<string> {"Get"},
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 8571
}
},
Key = "key3"
},
new FileReRoute
{
DownstreamPathTemplate = "/api/values?MailId={userid}",
UpstreamPathTemplate = "/key4data/{userid}",
UpstreamHttpMethod = new List<string> {"Get"},
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 8571
}
},
Key = "key4"
},
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
ReRouteKeys = new List<string>{
"key1",
"key2",
"key3",
"key4"
},
UpstreamPathTemplate = "/EmpDetail/IN/{userid}"
},
new FileAggregateReRoute
{
ReRouteKeys = new List<string>{
"key1",
"key2",
},
UpstreamPathTemplate = "/EmpDetail/US/{userid}"
}
},
GlobalConfiguration = new FileGlobalConfiguration
{
RequestIdKey = "CorrelationID"
}
};
var expected = "{\"key1\":some_data,\"key2\":some_data}";
this.Given(x => x.GivenServiceIsRunning("http://localhost:8571", 200, "some_data"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/EmpDetail/US/1"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe(expected))
.BDDfy();
}
[Fact] [Fact]
public void should_return_response_200_with_simple_url_user_defined_aggregate() public void should_return_response_200_with_simple_url_user_defined_aggregate()
{ {
@ -368,6 +478,15 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
private void GivenServiceIsRunning(string baseUrl, int statusCode, string responseBody)
{
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});
}
private void GivenServiceOneIsRunning(string baseUrl, string basePath, int statusCode, string responseBody) private void GivenServiceOneIsRunning(string baseUrl, string basePath, int statusCode, string responseBody)
{ {
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context => _serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>

View File

@ -0,0 +1,164 @@
namespace Ocelot.UnitTests.Configuration
{
using System.Collections.Generic;
using System.Net.Http;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Values;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class AggregatesCreatorTests
{
private readonly AggregatesCreator _creator;
private readonly Mock<IUpstreamTemplatePatternCreator> _utpCreator;
private FileConfiguration _fileConfiguration;
private List<ReRoute> _reRoutes;
private List<ReRoute> _result;
private UpstreamPathTemplate _aggregate1Utp;
private UpstreamPathTemplate _aggregate2Utp;
public AggregatesCreatorTests()
{
_utpCreator = new Mock<IUpstreamTemplatePatternCreator>();
_creator = new AggregatesCreator(_utpCreator.Object);
}
[Fact]
public void should_return_no_aggregates()
{
var fileConfig = new FileConfiguration
{
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
ReRouteKeys = new List<string>{"key1"}
}
}
};
var reRoutes = new List<ReRoute>();
this.Given(_ => GivenThe(fileConfig))
.And(_ => GivenThe(reRoutes))
.When(_ => WhenICreate())
.Then(_ => TheUtpCreatorIsNotCalled())
.And(_ => ThenTheResultIsNotNull())
.And(_ => ThenTheResultIsEmpty())
.BDDfy();
}
[Fact]
public void should_create_aggregates()
{
var fileConfig = new FileConfiguration
{
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
ReRouteKeys = new List<string>{"key1", "key2"},
UpstreamHost = "hosty",
UpstreamPathTemplate = "templatey",
Aggregator = "aggregatory",
ReRouteIsCaseSensitive = true
},
new FileAggregateReRoute
{
ReRouteKeys = new List<string>{"key3", "key4"},
UpstreamHost = "hosty",
UpstreamPathTemplate = "templatey",
Aggregator = "aggregatory",
ReRouteIsCaseSensitive = true
}
}
};
var reRoutes = new List<ReRoute>
{
new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().WithKey("key1").Build()).Build(),
new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().WithKey("key2").Build()).Build(),
new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().WithKey("key3").Build()).Build(),
new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().WithKey("key4").Build()).Build()
};
this.Given(_ => GivenThe(fileConfig))
.And(_ => GivenThe(reRoutes))
.And(_ => GivenTheUtpCreatorReturns())
.When(_ => WhenICreate())
.Then(_ => ThenTheUtpCreatorIsCalledCorrectly())
.And(_ => ThenTheAggregatesAreCreated())
.BDDfy();
}
private void ThenTheAggregatesAreCreated()
{
_result.ShouldNotBeNull();
_result.Count.ShouldBe(2);
_result[0].UpstreamHttpMethod.ShouldContain(x => x == HttpMethod.Get);
_result[0].UpstreamHost.ShouldBe(_fileConfiguration.Aggregates[0].UpstreamHost);
_result[0].UpstreamTemplatePattern.ShouldBe(_aggregate1Utp);
_result[0].Aggregator.ShouldBe(_fileConfiguration.Aggregates[0].Aggregator);
_result[0].DownstreamReRoute.ShouldContain(x => x == _reRoutes[0].DownstreamReRoute[0]);
_result[0].DownstreamReRoute.ShouldContain(x => x == _reRoutes[1].DownstreamReRoute[0]);
_result[1].UpstreamHttpMethod.ShouldContain(x => x == HttpMethod.Get);
_result[1].UpstreamHost.ShouldBe(_fileConfiguration.Aggregates[1].UpstreamHost);
_result[1].UpstreamTemplatePattern.ShouldBe(_aggregate2Utp);
_result[1].Aggregator.ShouldBe(_fileConfiguration.Aggregates[1].Aggregator);
_result[1].DownstreamReRoute.ShouldContain(x => x == _reRoutes[2].DownstreamReRoute[0]);
_result[1].DownstreamReRoute.ShouldContain(x => x == _reRoutes[3].DownstreamReRoute[0]);
}
private void ThenTheUtpCreatorIsCalledCorrectly()
{
_utpCreator.Verify(x => x.Create(_fileConfiguration.Aggregates[0]), Times.Once);
_utpCreator.Verify(x => x.Create(_fileConfiguration.Aggregates[1]), Times.Once);
}
private void GivenTheUtpCreatorReturns()
{
_aggregate1Utp = new UpstreamPathTemplateBuilder().Build();
_aggregate2Utp = new UpstreamPathTemplateBuilder().Build();
_utpCreator.SetupSequence(x => x.Create(It.IsAny<IReRoute>()))
.Returns(_aggregate1Utp)
.Returns(_aggregate2Utp);
}
private void ThenTheResultIsEmpty()
{
_result.Count.ShouldBe(0);
}
private void ThenTheResultIsNotNull()
{
_result.ShouldNotBeNull();
}
private void TheUtpCreatorIsNotCalled()
{
_utpCreator.Verify(x => x.Create(It.IsAny<FileAggregateReRoute>()), Times.Never);
}
private void GivenThe(FileConfiguration fileConfiguration)
{
_fileConfiguration = fileConfiguration;
}
private void GivenThe(List<ReRoute> reRoutes)
{
_reRoutes = reRoutes;
}
private void WhenICreate()
{
_result = _creator.Create(_fileConfiguration, _reRoutes);
}
}
}

View File

@ -0,0 +1,124 @@
namespace Ocelot.UnitTests.Configuration
{
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Ocelot.DependencyInjection;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class ConfigurationCreatorTests
{
private ConfigurationCreator _creator;
private InternalConfiguration _result;
private readonly Mock<IServiceProviderConfigurationCreator> _spcCreator;
private readonly Mock<IQoSOptionsCreator> _qosCreator;
private readonly Mock<IHttpHandlerOptionsCreator> _hhoCreator;
private readonly Mock<ILoadBalancerOptionsCreator> _lboCreator;
private FileConfiguration _fileConfig;
private List<ReRoute> _reRoutes;
private ServiceProviderConfiguration _spc;
private LoadBalancerOptions _lbo;
private QoSOptions _qoso;
private HttpHandlerOptions _hho;
private AdministrationPath _adminPath;
private readonly ServiceCollection _serviceCollection;
public ConfigurationCreatorTests()
{
_lboCreator = new Mock<ILoadBalancerOptionsCreator>();
_hhoCreator = new Mock<IHttpHandlerOptionsCreator>();
_qosCreator = new Mock<IQoSOptionsCreator>();
_spcCreator = new Mock<IServiceProviderConfigurationCreator>();
_serviceCollection = new ServiceCollection();
}
[Fact]
public void should_build_configuration_with_no_admin_path()
{
this.Given(_ => GivenTheDependenciesAreSetUp())
.When(_ => WhenICreate())
.Then(_ => ThenTheDepdenciesAreCalledCorrectly())
.And(_ => ThenThePropertiesAreSetCorrectly())
.And(_ => ThenTheAdminPathIsNull())
.BDDfy();
}
[Fact]
public void should_build_configuration_with_admin_path()
{
this.Given(_ => GivenTheDependenciesAreSetUp())
.And(_ => GivenTheAdminPath())
.When(_ => WhenICreate())
.Then(_ => ThenTheDepdenciesAreCalledCorrectly())
.And(_ => ThenThePropertiesAreSetCorrectly())
.And(_ => ThenTheAdminPathIsSet())
.BDDfy();
}
private void ThenTheAdminPathIsNull()
{
_result.AdministrationPath.ShouldBeNull();
}
private void ThenThePropertiesAreSetCorrectly()
{
_result.ShouldNotBeNull();
_result.ServiceProviderConfiguration.ShouldBe(_spc);
_result.LoadBalancerOptions.ShouldBe(_lbo);
_result.QoSOptions.ShouldBe(_qoso);
_result.HttpHandlerOptions.ShouldBe(_hho);
_result.ReRoutes.ShouldBe(_reRoutes);
_result.RequestId.ShouldBe(_fileConfig.GlobalConfiguration.RequestIdKey);
_result.DownstreamScheme.ShouldBe(_fileConfig.GlobalConfiguration.DownstreamScheme);
}
private void ThenTheAdminPathIsSet()
{
_result.AdministrationPath.ShouldBe("wooty");
}
private void ThenTheDepdenciesAreCalledCorrectly()
{
_spcCreator.Verify(x => x.Create(_fileConfig.GlobalConfiguration), Times.Once);
_lboCreator.Verify(x => x.Create(_fileConfig.GlobalConfiguration.LoadBalancerOptions), Times.Once);
_qosCreator.Verify(x => x.Create(_fileConfig.GlobalConfiguration.QoSOptions), Times.Once);
_hhoCreator.Verify(x => x.Create(_fileConfig.GlobalConfiguration.HttpHandlerOptions), Times.Once);
}
private void GivenTheAdminPath()
{
_adminPath = new AdministrationPath("wooty");
_serviceCollection.AddSingleton<IAdministrationPath>(_adminPath);
}
private void GivenTheDependenciesAreSetUp()
{
_fileConfig = new FileConfiguration
{
GlobalConfiguration = new FileGlobalConfiguration()
};
_reRoutes = new List<ReRoute>();
_spc = new ServiceProviderConfiguration("", "", 1, "", "", 1);
_lbo = new LoadBalancerOptionsBuilder().Build();
_qoso = new QoSOptions(1, 1, 1, "");
_hho = new HttpHandlerOptionsBuilder().Build();
_spcCreator.Setup(x => x.Create(It.IsAny<FileGlobalConfiguration>())).Returns(_spc);
_lboCreator.Setup(x => x.Create(It.IsAny<FileLoadBalancerOptions>())).Returns(_lbo);
_qosCreator.Setup(x => x.Create(It.IsAny<FileQoSOptions>())).Returns(_qoso);
_hhoCreator.Setup(x => x.Create(It.IsAny<FileHttpHandlerOptions>())).Returns(_hho);
}
private void WhenICreate()
{
var serviceProvider = _serviceCollection.BuildServiceProvider();
_creator = new ConfigurationCreator(_spcCreator.Object, _qosCreator.Object, _hhoCreator.Object, serviceProvider, _lboCreator.Object);
_result = _creator.Create(_fileConfig, _reRoutes);
}
}
}

View File

@ -0,0 +1,126 @@
namespace Ocelot.UnitTests.Configuration
{
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class DynamicsCreatorTests
{
private readonly DynamicsCreator _creator;
private readonly Mock<IRateLimitOptionsCreator> _rloCreator;
private List<ReRoute> _result;
private FileConfiguration _fileConfig;
private RateLimitOptions _rlo1;
private RateLimitOptions _rlo2;
public DynamicsCreatorTests()
{
_rloCreator = new Mock<IRateLimitOptionsCreator>();
_creator = new DynamicsCreator(_rloCreator.Object);
}
[Fact]
public void should_return_nothing()
{
var fileConfig = new FileConfiguration();
this.Given(_ => GivenThe(fileConfig))
.When(_ => WhenICreate())
.Then(_ => ThenNothingIsReturned())
.And(_ => ThenTheRloCreatorIsNotCalled())
.BDDfy();
}
[Fact]
public void should_return_re_routes()
{
var fileConfig = new FileConfiguration
{
DynamicReRoutes = new List<FileDynamicReRoute>
{
new FileDynamicReRoute
{
ServiceName = "1",
RateLimitRule = new FileRateLimitRule
{
EnableRateLimiting = false
}
},
new FileDynamicReRoute
{
ServiceName = "2",
RateLimitRule = new FileRateLimitRule
{
EnableRateLimiting = true
}
}
}
};
this.Given(_ => GivenThe(fileConfig))
.And(_ => GivenTheRloCreatorReturns())
.When(_ => WhenICreate())
.Then(_ => ThenTheReRoutesAreReturned())
.And(_ => ThenTheRloCreatorIsCalledCorrectly())
.BDDfy();
}
private void ThenTheRloCreatorIsCalledCorrectly()
{
_rloCreator.Verify(x => x.Create(_fileConfig.DynamicReRoutes[0].RateLimitRule,
_fileConfig.GlobalConfiguration), Times.Once);
_rloCreator.Verify(x => x.Create(_fileConfig.DynamicReRoutes[1].RateLimitRule,
_fileConfig.GlobalConfiguration), Times.Once);
}
private void ThenTheReRoutesAreReturned()
{
_result.Count.ShouldBe(2);
_result[0].DownstreamReRoute[0].EnableEndpointEndpointRateLimiting.ShouldBeFalse();
_result[0].DownstreamReRoute[0].RateLimitOptions.ShouldBe(_rlo1);
_result[0].DownstreamReRoute[0].ServiceName.ShouldBe(_fileConfig.DynamicReRoutes[0].ServiceName);
_result[1].DownstreamReRoute[0].EnableEndpointEndpointRateLimiting.ShouldBeTrue();
_result[1].DownstreamReRoute[0].RateLimitOptions.ShouldBe(_rlo2);
_result[1].DownstreamReRoute[0].ServiceName.ShouldBe(_fileConfig.DynamicReRoutes[1].ServiceName);
}
private void GivenTheRloCreatorReturns()
{
_rlo1 = new RateLimitOptionsBuilder().Build();
_rlo2 = new RateLimitOptionsBuilder().WithEnableRateLimiting(true).Build();
_rloCreator
.SetupSequence(x => x.Create(It.IsAny<FileRateLimitRule>(), It.IsAny<FileGlobalConfiguration>()))
.Returns(_rlo1)
.Returns(_rlo2);
}
private void ThenTheRloCreatorIsNotCalled()
{
_rloCreator.Verify(x => x.Create(It.IsAny<FileRateLimitRule>(), It.IsAny<FileGlobalConfiguration>()), Times.Never);
}
private void ThenNothingIsReturned()
{
_result.Count.ShouldBe(0);
}
private void WhenICreate()
{
_result = _creator.Create(_fileConfig);
}
private void GivenThe(FileConfiguration fileConfig)
{
_fileConfig = fileConfig;
}
}
}

View File

@ -0,0 +1,54 @@
namespace Ocelot.UnitTests.Configuration
{
using Ocelot.Configuration;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class LoadBalancerOptionsCreatorTests
{
private readonly ILoadBalancerOptionsCreator _creator;
private FileLoadBalancerOptions _fileLoadBalancerOptions;
private LoadBalancerOptions _result;
public LoadBalancerOptionsCreatorTests()
{
_creator = new LoadBalancerOptionsCreator();
}
[Fact]
public void should_create()
{
var fileLoadBalancerOptions = new FileLoadBalancerOptions
{
Type = "test",
Key = "west",
Expiry = 1
};
this.Given(_ => GivenThe(fileLoadBalancerOptions))
.When(_ => WhenICreate())
.Then(_ => ThenTheOptionsAreCreated(fileLoadBalancerOptions))
.BDDfy();
}
private void ThenTheOptionsAreCreated(FileLoadBalancerOptions expected)
{
_result.Type.ShouldBe(expected.Type);
_result.Key.ShouldBe(expected.Key);
_result.ExpiryInMs.ShouldBe(expected.Expiry);
}
private void WhenICreate()
{
_result = _creator.Create(_fileLoadBalancerOptions);
}
private void GivenThe(FileLoadBalancerOptions fileLoadBalancerOptions)
{
_fileLoadBalancerOptions = fileLoadBalancerOptions;
}
}
}

View File

@ -0,0 +1,85 @@
using System.Collections.Generic;
using System.Linq;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Ocelot.LoadBalancer.LoadBalancers;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Configuration
{
public class ReRouteKeyCreatorTests
{
private ReRouteKeyCreator _creator;
private FileReRoute _reRoute;
private string _result;
public ReRouteKeyCreatorTests()
{
_creator = new ReRouteKeyCreator();
}
[Fact]
public void should_return_sticky_session_key()
{
var reRoute = new FileReRoute
{
LoadBalancerOptions = new FileLoadBalancerOptions
{
Key = "testy",
Type = nameof(CookieStickySessions)
}
};
this.Given(_ => GivenThe(reRoute))
.When(_ => WhenICreate())
.Then(_ => ThenTheResultIs($"{nameof(CookieStickySessions)}:{reRoute.LoadBalancerOptions.Key}"))
.BDDfy();
}
[Fact]
public void should_return_re_route_key()
{
var reRoute = new FileReRoute
{
UpstreamPathTemplate = "/api/product",
UpstreamHttpMethod = new List<string> {"GET", "POST", "PUT"},
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 123
},
new FileHostAndPort
{
Host = "localhost",
Port = 123
}
}
};
this.Given(_ => GivenThe(reRoute))
.When(_ => WhenICreate())
.Then(_ => ThenTheResultIs($"{reRoute.UpstreamPathTemplate}|{string.Join(",", reRoute.UpstreamHttpMethod)}|{string.Join(",", reRoute.DownstreamHostAndPorts.Select(x => $"{x.Host}:{x.Port}"))}"))
.BDDfy();
}
private void GivenThe(FileReRoute reRoute)
{
_reRoute = reRoute;
}
private void WhenICreate()
{
_result = _creator.Create(_reRoute);
}
private void ThenTheResultIs(string expected)
{
_result.ShouldBe(expected);
}
}
}

View File

@ -1,17 +1,17 @@
using System.Collections.Generic;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Configuration namespace Ocelot.UnitTests.Configuration
{ {
using System.Collections.Generic;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class ReRouteOptionsCreatorTests public class ReRouteOptionsCreatorTests
{ {
private ReRouteOptionsCreator _creator; private readonly ReRouteOptionsCreator _creator;
private FileReRoute _reRoute; private FileReRoute _reRoute;
private ReRouteOptions _result; private ReRouteOptions _result;
@ -40,7 +40,8 @@ namespace Ocelot.UnitTests.Configuration
FileCacheOptions = new FileCacheOptions FileCacheOptions = new FileCacheOptions
{ {
TtlSeconds = 1 TtlSeconds = 1
} },
ServiceName = "west"
}; };
var expected = new ReRouteOptionsBuilder() var expected = new ReRouteOptionsBuilder()
@ -48,6 +49,7 @@ namespace Ocelot.UnitTests.Configuration
.WithIsAuthorised(true) .WithIsAuthorised(true)
.WithIsCached(true) .WithIsCached(true)
.WithRateLimiting(true) .WithRateLimiting(true)
.WithUseServiceDiscovery(true)
.Build(); .Build();
this.Given(x => x.GivenTheFollowing(reRoute)) this.Given(x => x.GivenTheFollowing(reRoute))
@ -72,6 +74,7 @@ namespace Ocelot.UnitTests.Configuration
_result.IsAuthorised.ShouldBe(expected.IsAuthorised); _result.IsAuthorised.ShouldBe(expected.IsAuthorised);
_result.IsCached.ShouldBe(expected.IsCached); _result.IsCached.ShouldBe(expected.IsCached);
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting); _result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
_result.UseServiceDiscovery.ShouldBe(expected.UseServiceDiscovery);
} }
} }
} }

View File

@ -0,0 +1,271 @@
namespace Ocelot.UnitTests.Configuration
{
using System;
using System.Collections.Generic;
using System.Linq;
using Moq;
using Ocelot.Cache;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Ocelot.Values;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class ReRoutesCreatorTests
{
private ReRoutesCreator _creator;
private Mock<IClaimsToThingCreator> _cthCreator;
private Mock<IAuthenticationOptionsCreator> _aoCreator;
private Mock<IUpstreamTemplatePatternCreator> _utpCreator;
private Mock<IRequestIdKeyCreator> _ridkCreator;
private Mock<IQoSOptionsCreator> _qosoCreator;
private Mock<IReRouteOptionsCreator> _rroCreator;
private Mock<IRateLimitOptionsCreator> _rloCreator;
private Mock<IRegionCreator> _rCreator;
private Mock<IHttpHandlerOptionsCreator> _hhoCreator;
private Mock<IHeaderFindAndReplaceCreator> _hfarCreator;
private Mock<IDownstreamAddressesCreator> _daCreator;
private Mock<ILoadBalancerOptionsCreator> _lboCreator;
private Mock<IReRouteKeyCreator> _rrkCreator;
private FileConfiguration _fileConfig;
private ReRouteOptions _rro;
private string _requestId;
private string _rrk;
private UpstreamPathTemplate _upt;
private AuthenticationOptions _ao;
private List<ClaimToThing> _ctt;
private QoSOptions _qoso;
private RateLimitOptions _rlo;
private string _region;
private HttpHandlerOptions _hho;
private HeaderTransformations _ht;
private List<DownstreamHostAndPort> _dhp;
private LoadBalancerOptions _lbo;
private List<ReRoute> _result;
public ReRoutesCreatorTests()
{
_cthCreator = new Mock<IClaimsToThingCreator>();
_aoCreator = new Mock<IAuthenticationOptionsCreator>();
_utpCreator = new Mock<IUpstreamTemplatePatternCreator>();
_ridkCreator = new Mock<IRequestIdKeyCreator>();
_qosoCreator = new Mock<IQoSOptionsCreator>();
_rroCreator = new Mock<IReRouteOptionsCreator>();
_rloCreator = new Mock<IRateLimitOptionsCreator>();
_rCreator = new Mock<IRegionCreator>();
_hhoCreator = new Mock<IHttpHandlerOptionsCreator>();
_hfarCreator = new Mock<IHeaderFindAndReplaceCreator>();
_daCreator = new Mock<IDownstreamAddressesCreator>();
_lboCreator = new Mock<ILoadBalancerOptionsCreator>();
_rrkCreator = new Mock<IReRouteKeyCreator>();
_creator = new ReRoutesCreator(
_cthCreator.Object,
_aoCreator.Object,
_utpCreator.Object,
_ridkCreator.Object,
_qosoCreator.Object,
_rroCreator.Object,
_rloCreator.Object,
_rCreator.Object,
_hhoCreator.Object,
_hfarCreator.Object,
_daCreator.Object,
_lboCreator.Object,
_rrkCreator.Object
);
}
[Fact]
public void should_return_nothing()
{
var fileConfig = new FileConfiguration();
this.Given(_ => GivenThe(fileConfig))
.When(_ => WhenICreate())
.Then(_ => ThenNoReRoutesAreReturned())
.BDDfy();
}
[Fact]
public void should_return_re_routes()
{
var fileConfig = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
ServiceName = "dave",
DangerousAcceptAnyServerCertificateValidator = true,
AddClaimsToRequest = new Dictionary<string, string>
{
{ "a","b" }
},
AddHeadersToRequest = new Dictionary<string, string>
{
{ "c","d" }
},
AddQueriesToRequest = new Dictionary<string, string>
{
{ "e","f" }
},
UpstreamHttpMethod = new List<string> { "GET", "POST" }
},
new FileReRoute
{
ServiceName = "wave",
DangerousAcceptAnyServerCertificateValidator = false,
AddClaimsToRequest = new Dictionary<string, string>
{
{ "g","h" }
},
AddHeadersToRequest = new Dictionary<string, string>
{
{ "i","j" }
},
AddQueriesToRequest = new Dictionary<string, string>
{
{ "k","l" }
},
UpstreamHttpMethod = new List<string> { "PUT", "DELETE" }
}
}
};
this.Given(_ => GivenThe(fileConfig))
.And(_ => GivenTheDependenciesAreSetUpCorrectly())
.When(_ => WhenICreate())
.Then(_ => ThenTheDependenciesAreCalledCorrectly())
.And(_ => ThenTheReRoutesAreCreated())
.BDDfy();
}
private void ThenTheDependenciesAreCalledCorrectly()
{
ThenTheDepsAreCalledFor(_fileConfig.ReRoutes[0], _fileConfig.GlobalConfiguration);
ThenTheDepsAreCalledFor(_fileConfig.ReRoutes[1], _fileConfig.GlobalConfiguration);
}
private void GivenTheDependenciesAreSetUpCorrectly()
{
_rro = new ReRouteOptions(false, false, false, false, false);
_requestId = "testy";
_rrk = "besty";
_upt = new UpstreamPathTemplateBuilder().Build();
_ao = new AuthenticationOptionsBuilder().Build();
_ctt = new List<ClaimToThing>();
_qoso = new QoSOptionsBuilder().Build();
_rlo = new RateLimitOptionsBuilder().Build();
_region = "vesty";
_hho = new HttpHandlerOptionsBuilder().Build();
_ht = new HeaderTransformations(new List<HeaderFindAndReplace>(), new List<HeaderFindAndReplace>(), new List<AddHeader>(), new List<AddHeader>());
_dhp = new List<DownstreamHostAndPort>();
_lbo = new LoadBalancerOptionsBuilder().Build();
_rroCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(_rro);
_ridkCreator.Setup(x => x.Create(It.IsAny<FileReRoute>(), It.IsAny<FileGlobalConfiguration>())).Returns(_requestId);
_rrkCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(_rrk);
_utpCreator.Setup(x => x.Create(It.IsAny<IReRoute>())).Returns(_upt);
_aoCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(_ao);
_cthCreator.Setup(x => x.Create(It.IsAny<Dictionary<string, string>>())).Returns(_ctt);
_qosoCreator.Setup(x => x.Create(It.IsAny<FileQoSOptions>(), It.IsAny<string>(), It.IsAny<List<string>>())).Returns(_qoso);
_rloCreator.Setup(x => x.Create(It.IsAny<FileRateLimitRule>(), It.IsAny<FileGlobalConfiguration>())).Returns(_rlo);
_rCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(_region);
_hhoCreator.Setup(x => x.Create(It.IsAny<FileHttpHandlerOptions>())).Returns(_hho);
_hfarCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(_ht);
_daCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(_dhp);
_lboCreator.Setup(x => x.Create(It.IsAny<FileLoadBalancerOptions>())).Returns(_lbo);
}
private void ThenTheReRoutesAreCreated()
{
_result.Count.ShouldBe(2);
ThenTheReRouteIsSet(_fileConfig.ReRoutes[0], 0);
ThenTheReRouteIsSet(_fileConfig.ReRoutes[1], 1);
}
private void ThenNoReRoutesAreReturned()
{
_result.ShouldBeEmpty();
}
private void GivenThe(FileConfiguration fileConfig)
{
_fileConfig = fileConfig;
}
private void WhenICreate()
{
_result = _creator.Create(_fileConfig);
}
private void ThenTheReRouteIsSet(FileReRoute expected, int reRouteIndex)
{
_result[reRouteIndex].DownstreamReRoute[0].IsAuthenticated.ShouldBe(_rro.IsAuthenticated);
_result[reRouteIndex].DownstreamReRoute[0].IsAuthorised.ShouldBe(_rro.IsAuthorised);
_result[reRouteIndex].DownstreamReRoute[0].IsCached.ShouldBe(_rro.IsCached);
_result[reRouteIndex].DownstreamReRoute[0].EnableEndpointEndpointRateLimiting.ShouldBe(_rro.EnableRateLimiting);
_result[reRouteIndex].DownstreamReRoute[0].RequestIdKey.ShouldBe(_requestId);
_result[reRouteIndex].DownstreamReRoute[0].LoadBalancerKey.ShouldBe(_rrk);
_result[reRouteIndex].DownstreamReRoute[0].UpstreamPathTemplate.ShouldBe(_upt);
_result[reRouteIndex].DownstreamReRoute[0].AuthenticationOptions.ShouldBe(_ao);
_result[reRouteIndex].DownstreamReRoute[0].ClaimsToHeaders.ShouldBe(_ctt);
_result[reRouteIndex].DownstreamReRoute[0].ClaimsToQueries.ShouldBe(_ctt);
_result[reRouteIndex].DownstreamReRoute[0].ClaimsToClaims.ShouldBe(_ctt);
_result[reRouteIndex].DownstreamReRoute[0].QosOptions.ShouldBe(_qoso);
_result[reRouteIndex].DownstreamReRoute[0].RateLimitOptions.ShouldBe(_rlo);
_result[reRouteIndex].DownstreamReRoute[0].CacheOptions.Region.ShouldBe(_region);
_result[reRouteIndex].DownstreamReRoute[0].CacheOptions.TtlSeconds.ShouldBe(expected.FileCacheOptions.TtlSeconds);
_result[reRouteIndex].DownstreamReRoute[0].HttpHandlerOptions.ShouldBe(_hho);
_result[reRouteIndex].DownstreamReRoute[0].UpstreamHeadersFindAndReplace.ShouldBe(_ht.Upstream);
_result[reRouteIndex].DownstreamReRoute[0].DownstreamHeadersFindAndReplace.ShouldBe(_ht.Downstream);
_result[reRouteIndex].DownstreamReRoute[0].AddHeadersToUpstream.ShouldBe(_ht.AddHeadersToUpstream);
_result[reRouteIndex].DownstreamReRoute[0].AddHeadersToDownstream.ShouldBe(_ht.AddHeadersToDownstream);
_result[reRouteIndex].DownstreamReRoute[0].DownstreamAddresses.ShouldBe(_dhp);
_result[reRouteIndex].DownstreamReRoute[0].LoadBalancerOptions.ShouldBe(_lbo);
_result[reRouteIndex].DownstreamReRoute[0].UseServiceDiscovery.ShouldBe(_rro.UseServiceDiscovery);
_result[reRouteIndex].DownstreamReRoute[0].DangerousAcceptAnyServerCertificateValidator.ShouldBe(expected.DangerousAcceptAnyServerCertificateValidator);
_result[reRouteIndex].DownstreamReRoute[0].DelegatingHandlers.ShouldBe(expected.DelegatingHandlers);
_result[reRouteIndex].DownstreamReRoute[0].ServiceName.ShouldBe(expected.ServiceName);
_result[reRouteIndex].DownstreamReRoute[0].DownstreamScheme.ShouldBe(expected.DownstreamScheme);
_result[reRouteIndex].DownstreamReRoute[0].RouteClaimsRequirement.ShouldBe(expected.RouteClaimsRequirement);
_result[reRouteIndex].DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe(expected.DownstreamPathTemplate);
_result[reRouteIndex].DownstreamReRoute[0].Key.ShouldBe(expected.Key);
_result[reRouteIndex].UpstreamHttpMethod
.Select(x => x.Method)
.ToList()
.ShouldContain(x => x == expected.UpstreamHttpMethod[0]);
_result[reRouteIndex].UpstreamHttpMethod
.Select(x => x.Method)
.ToList()
.ShouldContain(x => x == expected.UpstreamHttpMethod[1]);
_result[reRouteIndex].UpstreamHost.ShouldBe(expected.UpstreamHost);
_result[reRouteIndex].DownstreamReRoute.Count.ShouldBe(1);
_result[reRouteIndex].UpstreamTemplatePattern.ShouldBe(_upt);
}
private void ThenTheDepsAreCalledFor(FileReRoute fileReRoute, FileGlobalConfiguration globalConfig)
{
_rroCreator.Verify(x => x.Create(fileReRoute), Times.Once);
_ridkCreator.Verify(x => x.Create(fileReRoute, globalConfig), Times.Once);
_rrkCreator.Verify(x => x.Create(fileReRoute), Times.Once);
_utpCreator.Verify(x => x.Create(fileReRoute), Times.Exactly(2));
_aoCreator.Verify(x => x.Create(fileReRoute), Times.Once);
_cthCreator.Verify(x => x.Create(fileReRoute.AddHeadersToRequest), Times.Once);
_cthCreator.Verify(x => x.Create(fileReRoute.AddClaimsToRequest), Times.Once);
_cthCreator.Verify(x => x.Create(fileReRoute.AddQueriesToRequest), Times.Once);
_qosoCreator.Verify(x => x.Create(fileReRoute.QoSOptions, fileReRoute.UpstreamPathTemplate, fileReRoute.UpstreamHttpMethod));
_rloCreator.Verify(x => x.Create(fileReRoute.RateLimitOptions, globalConfig), Times.Once);
_rCreator.Verify(x => x.Create(fileReRoute), Times.Once);
_hhoCreator.Verify(x => x.Create(fileReRoute.HttpHandlerOptions), Times.Once);
_hfarCreator.Verify(x => x.Create(fileReRoute), Times.Once);
_daCreator.Verify(x => x.Create(fileReRoute), Times.Once);
_lboCreator.Verify(x => x.Create(fileReRoute.LoadBalancerOptions), Times.Once);
}
}
}

View File

@ -37,7 +37,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
_handlerOptions = new HttpHandlerOptionsBuilder().Build(); _handlerOptions = new HttpHandlerOptionsBuilder().Build();
_loadBalancerOptions = new LoadBalancerOptionsBuilder().WithType(nameof(NoLoadBalancer)).Build(); _loadBalancerOptions = new LoadBalancerOptionsBuilder().WithType(nameof(NoLoadBalancer)).Build();
_qosOptionsCreator _qosOptionsCreator
.Setup(x => x.Create(It.IsAny<QoSOptions>(), It.IsAny<string>(), It.IsAny<string[]>())) .Setup(x => x.Create(It.IsAny<QoSOptions>(), It.IsAny<string>(), It.IsAny<List<string>>()))
.Returns(_qoSOptions); .Returns(_qoSOptions);
_creator = new DownstreamRouteCreator(_qosOptionsCreator.Object); _creator = new DownstreamRouteCreator(_qosOptionsCreator.Object);
} }
@ -198,7 +198,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private void GivenTheQosCreatorReturns(QoSOptions options) private void GivenTheQosCreatorReturns(QoSOptions options)
{ {
_qosOptionsCreator _qosOptionsCreator
.Setup(x => x.Create(It.IsAny<QoSOptions>(), It.IsAny<string>(), It.IsAny<string[]>())) .Setup(x => x.Create(It.IsAny<QoSOptions>(), It.IsAny<string>(), It.IsAny<List<string>>()))
.Returns(options); .Returns(options);
} }
@ -260,7 +260,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
_result.Data.ReRoute.DownstreamReRoute[0].QosOptions.ShouldBe(expected); _result.Data.ReRoute.DownstreamReRoute[0].QosOptions.ShouldBe(expected);
_result.Data.ReRoute.DownstreamReRoute[0].QosOptions.UseQos.ShouldBeTrue(); _result.Data.ReRoute.DownstreamReRoute[0].QosOptions.UseQos.ShouldBeTrue();
_qosOptionsCreator _qosOptionsCreator
.Verify(x => x.Create(expected, _upstreamUrlPath, It.IsAny<string[]>()), Times.Once); .Verify(x => x.Create(expected, _upstreamUrlPath, It.IsAny<List<string>>()), Times.Once);
} }
private void GivenTheConfiguration(IInternalConfiguration config) private void GivenTheConfiguration(IInternalConfiguration config)

View File

@ -459,7 +459,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
.WithUpstreamHost("MATCH")
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
@ -545,7 +544,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
.WithUpstreamHost("MATCH")
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
@ -556,7 +554,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { }) // empty list of methods .WithUpstreamHttpMethod(new List<string> { }) // empty list of methods
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
.WithUpstreamHost("MATCH")
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { }) // empty list of methods .WithUpstreamHttpMethod(new List<string> { }) // empty list of methods
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
@ -587,7 +584,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string>()) .WithUpstreamHttpMethod(new List<string>())
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
.WithUpstreamHost("MATCH")
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string>()) .WithUpstreamHttpMethod(new List<string>())
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
@ -618,7 +614,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string>()) .WithUpstreamHttpMethod(new List<string>())
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
.WithUpstreamHost("MATCH")
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string>()) .WithUpstreamHttpMethod(new List<string>())
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
@ -659,7 +654,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))
.WithUpstreamHost("MATCH")
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath")) .WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "someUpstreamPath"))

View File

@ -1,63 +0,0 @@
namespace Ocelot.UnitTests.TestData
{
using System.Collections.Generic;
using Ocelot.Configuration.File;
public class AuthenticationConfigTestData
{
public static IEnumerable<object[]> GetAuthenticationData()
{
yield return new object[]
{
new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
AuthenticationOptions = new FileAuthenticationOptions
{
AuthenticationProviderKey = "Test",
AllowedScopes = new List<string>(),
},
AddHeadersToRequest =
{
{ "CustomerId", "Claims[CustomerId] > value" },
}
}
}
}
};
yield return new object[]
{
new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
AuthenticationOptions = new FileAuthenticationOptions
{
AuthenticationProviderKey = "Test",
AllowedScopes = new List<string>(),
},
AddHeadersToRequest =
{
{ "CustomerId", "Claims[CustomerId] > value" },
}
}
}
}
};
}
}
}