mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 14:02:49 +08:00
Merge pull request #58 from TomPallister/feature/refactor-config-creator
Feature/refactor config creator
This commit is contained in:
commit
a70a279487
71
src/Ocelot/Configuration/Builder/RateLimitOptionsBuilder.cs
Normal file
71
src/Ocelot/Configuration/Builder/RateLimitOptionsBuilder.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class RateLimitOptionsBuilder
|
||||
{
|
||||
private bool _enableRateLimiting;
|
||||
private string _clientIdHeader;
|
||||
private List<string> _clientWhitelist;
|
||||
private bool _disableRateLimitHeaders;
|
||||
private string _quotaExceededMessage;
|
||||
private string _rateLimitCounterPrefix;
|
||||
private RateLimitRule _rateLimitRule;
|
||||
private int _httpStatusCode;
|
||||
|
||||
public RateLimitOptionsBuilder WithEnableRateLimiting(bool enableRateLimiting)
|
||||
{
|
||||
_enableRateLimiting = enableRateLimiting;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithClientIdHeader(string clientIdheader)
|
||||
{
|
||||
_clientIdHeader = clientIdheader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithClientWhiteList(List<string> clientWhitelist)
|
||||
{
|
||||
_clientWhitelist = clientWhitelist;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithDisableRateLimitHeaders(bool disableRateLimitHeaders)
|
||||
{
|
||||
_disableRateLimitHeaders = disableRateLimitHeaders;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithQuotaExceededMessage(string quotaExceededMessage)
|
||||
{
|
||||
_quotaExceededMessage = quotaExceededMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithRateLimitCounterPrefix(string rateLimitCounterPrefix)
|
||||
{
|
||||
_rateLimitCounterPrefix = rateLimitCounterPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithRateLimitRule(RateLimitRule rateLimitRule)
|
||||
{
|
||||
_rateLimitRule = rateLimitRule;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptionsBuilder WithHttpStatusCode(int httpStatusCode)
|
||||
{
|
||||
_httpStatusCode = httpStatusCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RateLimitOptions Build()
|
||||
{
|
||||
return new RateLimitOptions(_enableRateLimiting, _clientIdHeader, _clientWhitelist,
|
||||
_disableRateLimitHeaders, _quotaExceededMessage, _rateLimitCounterPrefix,
|
||||
_rateLimitRule, _httpStatusCode);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ namespace Ocelot.Configuration.Builder
|
||||
private string _downstreamHost;
|
||||
private int _downstreamPort;
|
||||
private string _loadBalancer;
|
||||
private ServiceProviderConfiguraion _serviceProviderConfiguraion;
|
||||
private ServiceProviderConfiguration _serviceProviderConfiguraion;
|
||||
private bool _useQos;
|
||||
private QoSOptions _qosOptions;
|
||||
public bool _enableRateLimiting;
|
||||
@ -150,7 +150,7 @@ namespace Ocelot.Configuration.Builder
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithServiceProviderConfiguraion(ServiceProviderConfiguraion serviceProviderConfiguraion)
|
||||
public ReRouteBuilder WithServiceProviderConfiguraion(ServiceProviderConfiguration serviceProviderConfiguraion)
|
||||
{
|
||||
_serviceProviderConfiguraion = serviceProviderConfiguraion;
|
||||
return this;
|
||||
|
46
src/Ocelot/Configuration/Builder/ReRouteOptionsBuilder.cs
Normal file
46
src/Ocelot/Configuration/Builder/ReRouteOptionsBuilder.cs
Normal file
@ -0,0 +1,46 @@
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class ReRouteOptionsBuilder
|
||||
{
|
||||
private bool _isAuthenticated;
|
||||
private bool _isAuthorised;
|
||||
private bool _isCached;
|
||||
private bool _isQoS;
|
||||
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 WithIsQos(bool isQoS)
|
||||
{
|
||||
_isQoS = isQoS;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
|
||||
{
|
||||
_enableRateLimiting = enableRateLimiting;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptions Build()
|
||||
{
|
||||
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _isQoS, _enableRateLimiting);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class ServiceProviderConfiguraionBuilder
|
||||
public class ServiceProviderConfigurationBuilder
|
||||
{
|
||||
private string _serviceName;
|
||||
private string _downstreamHost;
|
||||
@ -10,52 +10,52 @@ namespace Ocelot.Configuration.Builder
|
||||
private string _serviceDiscoveryProviderHost;
|
||||
private int _serviceDiscoveryProviderPort;
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithServiceName(string serviceName)
|
||||
public ServiceProviderConfigurationBuilder WithServiceName(string serviceName)
|
||||
{
|
||||
_serviceName = serviceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithDownstreamHost(string downstreamHost)
|
||||
public ServiceProviderConfigurationBuilder WithDownstreamHost(string downstreamHost)
|
||||
{
|
||||
_downstreamHost = downstreamHost;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithDownstreamPort(int downstreamPort)
|
||||
public ServiceProviderConfigurationBuilder WithDownstreamPort(int downstreamPort)
|
||||
{
|
||||
_downstreamPort = downstreamPort;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithUseServiceDiscovery(bool userServiceDiscovery)
|
||||
public ServiceProviderConfigurationBuilder WithUseServiceDiscovery(bool userServiceDiscovery)
|
||||
{
|
||||
_userServiceDiscovery = userServiceDiscovery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithServiceDiscoveryProvider(string serviceDiscoveryProvider)
|
||||
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProvider(string serviceDiscoveryProvider)
|
||||
{
|
||||
_serviceDiscoveryProvider = serviceDiscoveryProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost)
|
||||
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost)
|
||||
{
|
||||
_serviceDiscoveryProviderHost = serviceDiscoveryProviderHost;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceProviderConfiguraionBuilder WithServiceDiscoveryProviderPort(int serviceDiscoveryProviderPort)
|
||||
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderPort(int serviceDiscoveryProviderPort)
|
||||
{
|
||||
_serviceDiscoveryProviderPort = serviceDiscoveryProviderPort;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ServiceProviderConfiguraion Build()
|
||||
public ServiceProviderConfiguration Build()
|
||||
{
|
||||
return new ServiceProviderConfiguraion(_serviceName, _downstreamHost, _downstreamPort, _userServiceDiscovery,
|
||||
return new ServiceProviderConfiguration(_serviceName, _downstreamHost, _downstreamPort, _userServiceDiscovery,
|
||||
_serviceDiscoveryProvider, _serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class AuthenticationOptionsCreator : IAuthenticationOptionsCreator
|
||||
{
|
||||
public AuthenticationOptions Create(FileReRoute fileReRoute)
|
||||
{
|
||||
return new AuthenticationOptionsBuilder()
|
||||
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
||||
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.ProviderRootUrl)
|
||||
.WithScopeName(fileReRoute.AuthenticationOptions?.ScopeName)
|
||||
.WithRequireHttps(fileReRoute.AuthenticationOptions.RequireHttps)
|
||||
.WithAdditionalScopes(fileReRoute.AuthenticationOptions?.AdditionalScopes)
|
||||
.WithScopeSecret(fileReRoute.AuthenticationOptions?.ScopeSecret)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
41
src/Ocelot/Configuration/Creator/ClaimsToThingCreator.cs
Normal file
41
src/Ocelot/Configuration/Creator/ClaimsToThingCreator.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
using Ocelot.Configuration.Parser;
|
||||
using Ocelot.Logging;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class ClaimsToThingCreator : IClaimsToThingCreator
|
||||
{
|
||||
private readonly IClaimToThingConfigurationParser _claimToThingConfigParser;
|
||||
private readonly IOcelotLogger _logger;
|
||||
|
||||
public ClaimsToThingCreator(IClaimToThingConfigurationParser claimToThingConfigurationParser,
|
||||
IOcelotLoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<ClaimsToThingCreator>();
|
||||
_claimToThingConfigParser = claimToThingConfigurationParser;
|
||||
}
|
||||
|
||||
public List<ClaimToThing> Create(Dictionary<string,string> inputToBeParsed)
|
||||
{
|
||||
var claimsToThings = new List<ClaimToThing>();
|
||||
|
||||
foreach (var input in inputToBeParsed)
|
||||
{
|
||||
var claimToThing = _claimToThingConfigParser.Extract(input.Key, input.Value);
|
||||
|
||||
if (claimToThing.IsError)
|
||||
{
|
||||
_logger.LogDebug("ClaimsToThingCreator.BuildAddThingsToRequest",
|
||||
$"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
|
||||
}
|
||||
else
|
||||
{
|
||||
claimsToThings.Add(claimToThing.Data);
|
||||
}
|
||||
}
|
||||
|
||||
return claimsToThings;
|
||||
}
|
||||
}
|
||||
}
|
@ -22,36 +22,53 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
private readonly IOptions<FileConfiguration> _options;
|
||||
private readonly IConfigurationValidator _configurationValidator;
|
||||
private const string RegExMatchEverything = ".*";
|
||||
private const string RegExMatchEndString = "$";
|
||||
private const string RegExIgnoreCase = "(?i)";
|
||||
private const string RegExForwardSlashOnly = "^/$";
|
||||
|
||||
private readonly IClaimToThingConfigurationParser _claimToThingConfigurationParser;
|
||||
private readonly ILogger<FileOcelotConfigurationCreator> _logger;
|
||||
private readonly ILoadBalancerFactory _loadBalanceFactory;
|
||||
private readonly ILoadBalancerHouse _loadBalancerHouse;
|
||||
private readonly IQoSProviderFactory _qoSProviderFactory;
|
||||
private readonly IQosProviderHouse _qosProviderHouse;
|
||||
private readonly IClaimsToThingCreator _claimsToThingCreator;
|
||||
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
|
||||
private IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
|
||||
private IRequestIdKeyCreator _requestIdKeyCreator;
|
||||
private IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
|
||||
private IQoSOptionsCreator _qosOptionsCreator;
|
||||
private IReRouteOptionsCreator _fileReRouteOptionsCreator;
|
||||
private IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||
|
||||
public FileOcelotConfigurationCreator(
|
||||
IOptions<FileConfiguration> options,
|
||||
IConfigurationValidator configurationValidator,
|
||||
IClaimToThingConfigurationParser claimToThingConfigurationParser,
|
||||
ILogger<FileOcelotConfigurationCreator> logger,
|
||||
ILoadBalancerFactory loadBalancerFactory,
|
||||
ILoadBalancerHouse loadBalancerHouse,
|
||||
IQoSProviderFactory qoSProviderFactory,
|
||||
IQosProviderHouse qosProviderHouse)
|
||||
IQosProviderHouse qosProviderHouse,
|
||||
IClaimsToThingCreator claimsToThingCreator,
|
||||
IAuthenticationOptionsCreator authOptionsCreator,
|
||||
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
|
||||
IRequestIdKeyCreator requestIdKeyCreator,
|
||||
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
||||
IQoSOptionsCreator qosOptionsCreator,
|
||||
IReRouteOptionsCreator fileReRouteOptionsCreator,
|
||||
IRateLimitOptionsCreator rateLimitOptionsCreator
|
||||
)
|
||||
{
|
||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||
_requestIdKeyCreator = requestIdKeyCreator;
|
||||
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
||||
_authOptionsCreator = authOptionsCreator;
|
||||
_loadBalanceFactory = loadBalancerFactory;
|
||||
_loadBalancerHouse = loadBalancerHouse;
|
||||
_qoSProviderFactory = qoSProviderFactory;
|
||||
_qosProviderHouse = qosProviderHouse;
|
||||
_options = options;
|
||||
_configurationValidator = configurationValidator;
|
||||
_claimToThingConfigurationParser = claimToThingConfigurationParser;
|
||||
_logger = logger;
|
||||
_claimsToThingCreator = claimsToThingCreator;
|
||||
_serviceProviderConfigCreator = serviceProviderConfigCreator;
|
||||
_qosOptionsCreator = qosOptionsCreator;
|
||||
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
|
||||
}
|
||||
|
||||
public async Task<Response<IOcelotConfiguration>> Create()
|
||||
@ -97,50 +114,42 @@ namespace Ocelot.Configuration.Creator
|
||||
|
||||
private async Task<ReRoute> SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var isAuthenticated = IsAuthenticated(fileReRoute);
|
||||
var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute);
|
||||
|
||||
var isAuthorised = IsAuthorised(fileReRoute);
|
||||
var requestIdKey = _requestIdKeyCreator.Create(fileReRoute, globalConfiguration);
|
||||
|
||||
var isCached = IsCached(fileReRoute);
|
||||
var reRouteKey = CreateReRouteKey(fileReRoute);
|
||||
|
||||
var requestIdKey = BuildRequestId(fileReRoute, globalConfiguration);
|
||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
||||
|
||||
var reRouteKey = BuildReRouteKey(fileReRoute);
|
||||
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileReRoute, globalConfiguration);
|
||||
|
||||
var upstreamTemplatePattern = BuildUpstreamTemplatePattern(fileReRoute);
|
||||
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
|
||||
|
||||
var isQos = IsQoS(fileReRoute);
|
||||
var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
|
||||
|
||||
var serviceProviderConfiguration = BuildServiceProviderConfiguration(fileReRoute, globalConfiguration);
|
||||
var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
|
||||
|
||||
var authOptionsForRoute = BuildAuthenticationOptions(fileReRoute);
|
||||
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
|
||||
|
||||
var claimsToHeaders = BuildAddThingsToRequest(fileReRoute.AddHeadersToRequest);
|
||||
var qosOptions = _qosOptionsCreator.Create(fileReRoute);
|
||||
|
||||
var claimsToClaims = BuildAddThingsToRequest(fileReRoute.AddClaimsToRequest);
|
||||
|
||||
var claimsToQueries = BuildAddThingsToRequest(fileReRoute.AddQueriesToRequest);
|
||||
|
||||
var qosOptions = BuildQoSOptions(fileReRoute);
|
||||
|
||||
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
|
||||
|
||||
var rateLimitOption = BuildRateLimitOptions(fileReRoute, globalConfiguration, enableRateLimiting);
|
||||
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
|
||||
.WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
|
||||
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamTemplatePattern(upstreamTemplatePattern)
|
||||
.WithIsAuthenticated(isAuthenticated)
|
||||
.WithIsAuthenticated(fileReRouteOptions.IsAuthenticated)
|
||||
.WithAuthenticationOptions(authOptionsForRoute)
|
||||
.WithClaimsToHeaders(claimsToHeaders)
|
||||
.WithClaimsToClaims(claimsToClaims)
|
||||
.WithRouteClaimsRequirement(fileReRoute.RouteClaimsRequirement)
|
||||
.WithIsAuthorised(isAuthorised)
|
||||
.WithIsAuthorised(fileReRouteOptions.IsAuthorised)
|
||||
.WithClaimsToQueries(claimsToQueries)
|
||||
.WithRequestIdKey(requestIdKey)
|
||||
.WithIsCached(isCached)
|
||||
.WithIsCached(fileReRouteOptions.IsCached)
|
||||
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds))
|
||||
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
||||
.WithLoadBalancer(fileReRoute.LoadBalancer)
|
||||
@ -148,95 +157,24 @@ namespace Ocelot.Configuration.Creator
|
||||
.WithDownstreamPort(fileReRoute.DownstreamPort)
|
||||
.WithLoadBalancerKey(reRouteKey)
|
||||
.WithServiceProviderConfiguraion(serviceProviderConfiguration)
|
||||
.WithIsQos(isQos)
|
||||
.WithIsQos(fileReRouteOptions.IsQos)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithEnableRateLimiting(enableRateLimiting)
|
||||
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
|
||||
.WithRateLimitOptions(rateLimitOption)
|
||||
.Build();
|
||||
|
||||
await SetupLoadBalancer(reRoute);
|
||||
SetupQosProvider(reRoute);
|
||||
return reRoute;
|
||||
}
|
||||
|
||||
private static RateLimitOptions BuildRateLimitOptions(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration, bool enableRateLimiting)
|
||||
{
|
||||
RateLimitOptions rateLimitOption = null;
|
||||
if (enableRateLimiting)
|
||||
{
|
||||
rateLimitOption = new RateLimitOptions(enableRateLimiting, globalConfiguration.RateLimitOptions.ClientIdHeader,
|
||||
fileReRoute.RateLimitOptions.ClientWhitelist, globalConfiguration.RateLimitOptions.DisableRateLimitHeaders,
|
||||
globalConfiguration.RateLimitOptions.QuotaExceededMessage, globalConfiguration.RateLimitOptions.RateLimitCounterPrefix,
|
||||
new RateLimitRule(fileReRoute.RateLimitOptions.Period, TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan), fileReRoute.RateLimitOptions.Limit)
|
||||
, globalConfiguration.RateLimitOptions.HttpStatusCode);
|
||||
}
|
||||
|
||||
return rateLimitOption;
|
||||
}
|
||||
|
||||
private static bool IsEnableRateLimiting(FileReRoute fileReRoute)
|
||||
{
|
||||
return (fileReRoute.RateLimitOptions != null && fileReRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
|
||||
}
|
||||
|
||||
private QoSOptions BuildQoSOptions(FileReRoute fileReRoute)
|
||||
{
|
||||
return new QoSOptionsBuilder()
|
||||
.WithExceptionsAllowedBeforeBreaking(fileReRoute.QoSOptions.ExceptionsAllowedBeforeBreaking)
|
||||
.WithDurationOfBreak(fileReRoute.QoSOptions.DurationOfBreak)
|
||||
.WithTimeoutValue(fileReRoute.QoSOptions.TimeoutValue)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private bool IsQoS(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.QoSOptions?.ExceptionsAllowedBeforeBreaking > 0 && fileReRoute.QoSOptions?.TimeoutValue > 0;
|
||||
}
|
||||
|
||||
private bool IsAuthenticated(FileReRoute fileReRoute)
|
||||
{
|
||||
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.Provider);
|
||||
}
|
||||
|
||||
private bool IsAuthorised(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.RouteClaimsRequirement?.Count > 0;
|
||||
}
|
||||
|
||||
private bool IsCached(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.FileCacheOptions.TtlSeconds > 0;
|
||||
}
|
||||
|
||||
private string BuildRequestId(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var globalRequestIdConfiguration = !string.IsNullOrEmpty(globalConfiguration?.RequestIdKey);
|
||||
|
||||
var requestIdKey = globalRequestIdConfiguration
|
||||
? globalConfiguration.RequestIdKey
|
||||
: fileReRoute.RequestIdKey;
|
||||
|
||||
return requestIdKey;
|
||||
}
|
||||
|
||||
private string BuildReRouteKey(FileReRoute fileReRoute)
|
||||
private string CreateReRouteKey(FileReRoute fileReRoute)
|
||||
{
|
||||
//note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
|
||||
var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}{fileReRoute.UpstreamHttpMethod}";
|
||||
return loadBalancerKey;
|
||||
}
|
||||
|
||||
private AuthenticationOptions BuildAuthenticationOptions(FileReRoute fileReRoute)
|
||||
{
|
||||
return new AuthenticationOptionsBuilder()
|
||||
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
||||
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.ProviderRootUrl)
|
||||
.WithScopeName(fileReRoute.AuthenticationOptions?.ScopeName)
|
||||
.WithRequireHttps(fileReRoute.AuthenticationOptions.RequireHttps)
|
||||
.WithAdditionalScopes(fileReRoute.AuthenticationOptions?.AdditionalScopes)
|
||||
.WithScopeSecret(fileReRoute.AuthenticationOptions?.ScopeSecret)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private async Task SetupLoadBalancer(ReRoute reRoute)
|
||||
{
|
||||
var loadBalancer = await _loadBalanceFactory.Get(reRoute);
|
||||
@ -248,85 +186,5 @@ namespace Ocelot.Configuration.Creator
|
||||
var loadBalancer = _qoSProviderFactory.Get(reRoute);
|
||||
_qosProviderHouse.Add(reRoute.ReRouteKey, loadBalancer);
|
||||
}
|
||||
|
||||
private ServiceProviderConfiguraion BuildServiceProviderConfiguration(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName)
|
||||
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
|
||||
|
||||
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||
|
||||
return new ServiceProviderConfiguraionBuilder()
|
||||
.WithServiceName(fileReRoute.ServiceName)
|
||||
.WithDownstreamHost(fileReRoute.DownstreamHost)
|
||||
.WithDownstreamPort(fileReRoute.DownstreamPort)
|
||||
.WithUseServiceDiscovery(useServiceDiscovery)
|
||||
.WithServiceDiscoveryProvider(globalConfiguration?.ServiceDiscoveryProvider?.Provider)
|
||||
.WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
|
||||
.WithServiceDiscoveryProviderPort(serviceProviderPort)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private string BuildUpstreamTemplatePattern(FileReRoute reRoute)
|
||||
{
|
||||
var upstreamTemplate = reRoute.UpstreamPathTemplate;
|
||||
|
||||
upstreamTemplate = upstreamTemplate.SetLastCharacterAs('/');
|
||||
|
||||
var placeholders = new List<string>();
|
||||
|
||||
for (var i = 0; i < upstreamTemplate.Length; i++)
|
||||
{
|
||||
if (IsPlaceHolder(upstreamTemplate, i))
|
||||
{
|
||||
var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i);
|
||||
var difference = postitionOfPlaceHolderClosingBracket - i + 1;
|
||||
var variableName = upstreamTemplate.Substring(i, difference);
|
||||
placeholders.Add(variableName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var placeholder in placeholders)
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchEverything);
|
||||
}
|
||||
|
||||
if (upstreamTemplate == "/")
|
||||
{
|
||||
return RegExForwardSlashOnly;
|
||||
}
|
||||
|
||||
var route = reRoute.ReRouteIsCaseSensitive
|
||||
? $"{upstreamTemplate}{RegExMatchEndString}"
|
||||
: $"{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
private List<ClaimToThing> BuildAddThingsToRequest(Dictionary<string,string> thingBeingAdded)
|
||||
{
|
||||
var claimsToTHings = new List<ClaimToThing>();
|
||||
|
||||
foreach (var add in thingBeingAdded)
|
||||
{
|
||||
var claimToHeader = _claimToThingConfigurationParser.Extract(add.Key, add.Value);
|
||||
|
||||
if (claimToHeader.IsError)
|
||||
{
|
||||
_logger.LogCritical(new EventId(1, "Application Failed to start"),
|
||||
$"Unable to extract configuration for key: {add.Key} and value: {add.Value} your configuration file is incorrect");
|
||||
|
||||
throw new Exception(claimToHeader.Errors[0].Message);
|
||||
}
|
||||
claimsToTHings.Add(claimToHeader.Data);
|
||||
}
|
||||
|
||||
return claimsToTHings;
|
||||
}
|
||||
|
||||
private bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||
{
|
||||
return upstreamTemplate[i] == '{';
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IAuthenticationOptionsCreator
|
||||
{
|
||||
AuthenticationOptions Create(FileReRoute fileReRoute);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IClaimsToThingCreator
|
||||
{
|
||||
List<ClaimToThing> Create(Dictionary<string,string> thingsBeingAdded);
|
||||
}
|
||||
}
|
9
src/Ocelot/Configuration/Creator/IQoSOptionsCreator.cs
Normal file
9
src/Ocelot/Configuration/Creator/IQoSOptionsCreator.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IQoSOptionsCreator
|
||||
{
|
||||
QoSOptions Create(FileReRoute fileReRoute);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IRateLimitOptionsCreator
|
||||
{
|
||||
RateLimitOptions Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration, bool enableRateLimiting);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IReRouteOptionsCreator
|
||||
{
|
||||
ReRouteOptions Create(FileReRoute fileReRoute);
|
||||
}
|
||||
}
|
9
src/Ocelot/Configuration/Creator/IRequestIdKeyCreator.cs
Normal file
9
src/Ocelot/Configuration/Creator/IRequestIdKeyCreator.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IRequestIdKeyCreator
|
||||
{
|
||||
string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IServiceProviderConfigurationCreator
|
||||
{
|
||||
ServiceProviderConfiguration Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IUpstreamTemplatePatternCreator
|
||||
{
|
||||
string Create(FileReRoute reRoute);
|
||||
}
|
||||
}
|
17
src/Ocelot/Configuration/Creator/QoSOptionsCreator.cs
Normal file
17
src/Ocelot/Configuration/Creator/QoSOptionsCreator.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class QoSOptionsCreator : IQoSOptionsCreator
|
||||
{
|
||||
public QoSOptions Create(FileReRoute fileReRoute)
|
||||
{
|
||||
return new QoSOptionsBuilder()
|
||||
.WithExceptionsAllowedBeforeBreaking(fileReRoute.QoSOptions.ExceptionsAllowedBeforeBreaking)
|
||||
.WithDurationOfBreak(fileReRoute.QoSOptions.DurationOfBreak)
|
||||
.WithTimeoutValue(fileReRoute.QoSOptions.TimeoutValue)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
32
src/Ocelot/Configuration/Creator/RateLimitOptionsCreator.cs
Normal file
32
src/Ocelot/Configuration/Creator/RateLimitOptionsCreator.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class RateLimitOptionsCreator : IRateLimitOptionsCreator
|
||||
{
|
||||
public RateLimitOptions Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration, bool enableRateLimiting)
|
||||
{
|
||||
RateLimitOptions rateLimitOption = null;
|
||||
|
||||
if (enableRateLimiting)
|
||||
{
|
||||
rateLimitOption = new RateLimitOptionsBuilder()
|
||||
.WithClientIdHeader(globalConfiguration.RateLimitOptions.ClientIdHeader)
|
||||
.WithClientWhiteList(fileReRoute.RateLimitOptions.ClientWhitelist)
|
||||
.WithDisableRateLimitHeaders(globalConfiguration.RateLimitOptions.DisableRateLimitHeaders)
|
||||
.WithEnableRateLimiting(fileReRoute.RateLimitOptions.EnableRateLimiting)
|
||||
.WithHttpStatusCode(globalConfiguration.RateLimitOptions.HttpStatusCode)
|
||||
.WithQuotaExceededMessage(globalConfiguration.RateLimitOptions.QuotaExceededMessage)
|
||||
.WithRateLimitCounterPrefix(globalConfiguration.RateLimitOptions.RateLimitCounterPrefix)
|
||||
.WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
|
||||
TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan),
|
||||
fileReRoute.RateLimitOptions.Limit))
|
||||
.Build();
|
||||
}
|
||||
|
||||
return rateLimitOption;
|
||||
}
|
||||
}
|
||||
}
|
52
src/Ocelot/Configuration/Creator/ReRouteOptionsCreator.cs
Normal file
52
src/Ocelot/Configuration/Creator/ReRouteOptionsCreator.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class ReRouteOptionsCreator : IReRouteOptionsCreator
|
||||
{
|
||||
public ReRouteOptions Create(FileReRoute fileReRoute)
|
||||
{
|
||||
var isAuthenticated = IsAuthenticated(fileReRoute);
|
||||
var isAuthorised = IsAuthorised(fileReRoute);
|
||||
var isCached = IsCached(fileReRoute);
|
||||
var isQos = IsQoS(fileReRoute);
|
||||
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
|
||||
|
||||
var options = new ReRouteOptionsBuilder()
|
||||
.WithIsAuthenticated(isAuthenticated)
|
||||
.WithIsAuthorised(isAuthorised)
|
||||
.WithIsCached(isCached)
|
||||
.WithIsQos(isQos)
|
||||
.WithRateLimiting(enableRateLimiting)
|
||||
.Build();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static bool IsEnableRateLimiting(FileReRoute fileReRoute)
|
||||
{
|
||||
return (fileReRoute.RateLimitOptions != null && fileReRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
|
||||
}
|
||||
|
||||
private bool IsQoS(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.QoSOptions?.ExceptionsAllowedBeforeBreaking > 0 && fileReRoute.QoSOptions?.TimeoutValue > 0;
|
||||
}
|
||||
|
||||
private bool IsAuthenticated(FileReRoute fileReRoute)
|
||||
{
|
||||
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.Provider);
|
||||
}
|
||||
|
||||
private bool IsAuthorised(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.RouteClaimsRequirement?.Count > 0;
|
||||
}
|
||||
|
||||
private bool IsCached(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.FileCacheOptions.TtlSeconds > 0;
|
||||
}
|
||||
}
|
||||
}
|
18
src/Ocelot/Configuration/Creator/RequestIdKeyCreator.cs
Normal file
18
src/Ocelot/Configuration/Creator/RequestIdKeyCreator.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class RequestIdKeyCreator : IRequestIdKeyCreator
|
||||
{
|
||||
public string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var globalRequestIdConfiguration = !string.IsNullOrEmpty(globalConfiguration?.RequestIdKey);
|
||||
|
||||
var requestIdKey = globalRequestIdConfiguration
|
||||
? globalConfiguration.RequestIdKey
|
||||
: fileReRoute.RequestIdKey;
|
||||
|
||||
return requestIdKey;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class ServiceProviderConfigurationCreator : IServiceProviderConfigurationCreator
|
||||
{
|
||||
public ServiceProviderConfiguration Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName)
|
||||
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
|
||||
|
||||
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||
|
||||
return new ServiceProviderConfigurationBuilder()
|
||||
.WithServiceName(fileReRoute.ServiceName)
|
||||
.WithDownstreamHost(fileReRoute.DownstreamHost)
|
||||
.WithDownstreamPort(fileReRoute.DownstreamPort)
|
||||
.WithUseServiceDiscovery(useServiceDiscovery)
|
||||
.WithServiceDiscoveryProvider(globalConfiguration?.ServiceDiscoveryProvider?.Provider)
|
||||
.WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
|
||||
.WithServiceDiscoveryProviderPort(serviceProviderPort)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Utilities;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator
|
||||
{
|
||||
private const string RegExMatchEverything = ".*";
|
||||
private const string RegExMatchEndString = "$";
|
||||
private const string RegExIgnoreCase = "(?i)";
|
||||
private const string RegExForwardSlashOnly = "^/$";
|
||||
|
||||
public string Create(FileReRoute reRoute)
|
||||
{
|
||||
var upstreamTemplate = reRoute.UpstreamPathTemplate;
|
||||
|
||||
upstreamTemplate = upstreamTemplate.SetLastCharacterAs('/');
|
||||
|
||||
var placeholders = new List<string>();
|
||||
|
||||
for (var i = 0; i < upstreamTemplate.Length; i++)
|
||||
{
|
||||
if (IsPlaceHolder(upstreamTemplate, i))
|
||||
{
|
||||
var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i);
|
||||
var difference = postitionOfPlaceHolderClosingBracket - i + 1;
|
||||
var variableName = upstreamTemplate.Substring(i, difference);
|
||||
placeholders.Add(variableName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var placeholder in placeholders)
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchEverything);
|
||||
}
|
||||
|
||||
if (upstreamTemplate == "/")
|
||||
{
|
||||
return RegExForwardSlashOnly;
|
||||
}
|
||||
|
||||
var route = reRoute.ReRouteIsCaseSensitive
|
||||
? $"{upstreamTemplate}{RegExMatchEndString}"
|
||||
: $"{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
|
||||
private bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||
{
|
||||
return upstreamTemplate[i] == '{';
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ namespace Ocelot.Configuration
|
||||
string downstreamHost,
|
||||
int downstreamPort,
|
||||
string reRouteKey,
|
||||
ServiceProviderConfiguraion serviceProviderConfiguraion,
|
||||
ServiceProviderConfiguration serviceProviderConfiguraion,
|
||||
bool isQos,
|
||||
QoSOptions qos,
|
||||
bool enableRateLimit,
|
||||
@ -81,7 +81,7 @@ namespace Ocelot.Configuration
|
||||
public string LoadBalancer {get;private set;}
|
||||
public string DownstreamHost { get; private set; }
|
||||
public int DownstreamPort { get; private set; }
|
||||
public ServiceProviderConfiguraion ServiceProviderConfiguraion { get; private set; }
|
||||
public ServiceProviderConfiguration ServiceProviderConfiguraion { get; private set; }
|
||||
public bool EnableEndpointRateLimiting { get; private set; }
|
||||
public RateLimitOptions RateLimitOptions { get; private set; }
|
||||
}
|
||||
|
20
src/Ocelot/Configuration/ReRouteOptions.cs
Normal file
20
src/Ocelot/Configuration/ReRouteOptions.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
public class ReRouteOptions
|
||||
{
|
||||
public ReRouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isQos, bool isEnableRateLimiting)
|
||||
{
|
||||
IsAuthenticated = isAuthenticated;
|
||||
IsAuthorised = isAuthorised;
|
||||
IsCached = isCached;
|
||||
IsQos = isQos;
|
||||
EnableRateLimiting = isEnableRateLimiting;
|
||||
|
||||
}
|
||||
public bool IsAuthenticated { get; private set; }
|
||||
public bool IsAuthorised { get; private set; }
|
||||
public bool IsCached { get; private set; }
|
||||
public bool IsQos { get; private set; }
|
||||
public bool EnableRateLimiting { get; private set; }
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
public class ServiceProviderConfiguraion
|
||||
public class ServiceProviderConfiguration
|
||||
{
|
||||
public ServiceProviderConfiguraion(string serviceName, string downstreamHost,
|
||||
public ServiceProviderConfiguration(string serviceName, string downstreamHost,
|
||||
int downstreamPort, bool useServiceDiscovery, string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort)
|
||||
{
|
||||
ServiceName = serviceName;
|
||||
|
@ -60,6 +60,14 @@ namespace Ocelot.DependencyInjection
|
||||
services.AddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
|
||||
services.AddSingleton<IConfigurationValidator, FileConfigurationValidator>();
|
||||
services.AddSingleton<IBaseUrlFinder, BaseUrlFinder>();
|
||||
services.AddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>();
|
||||
services.AddSingleton<IAuthenticationOptionsCreator, AuthenticationOptionsCreator>();
|
||||
services.AddSingleton<IUpstreamTemplatePatternCreator, UpstreamTemplatePatternCreator>();
|
||||
services.AddSingleton<IRequestIdKeyCreator, RequestIdKeyCreator>();
|
||||
services.AddSingleton<IServiceProviderConfigurationCreator,ServiceProviderConfigurationCreator>();
|
||||
services.AddSingleton<IQoSOptionsCreator, QoSOptionsCreator>();
|
||||
services.AddSingleton<IReRouteOptionsCreator, ReRouteOptionsCreator>();
|
||||
services.AddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>();
|
||||
|
||||
var identityServerConfiguration = IdentityServerConfigurationCreator.GetIdentityServerConfiguration();
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using Ocelot.Configuration;
|
||||
|
||||
namespace Ocelot.ServiceDiscovery
|
||||
{
|
||||
public interface IServiceDiscoveryProviderFactory
|
||||
{
|
||||
IServiceDiscoveryProvider Get(ServiceProviderConfiguraion serviceConfig);
|
||||
IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ namespace Ocelot.ServiceDiscovery
|
||||
{
|
||||
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
|
||||
{
|
||||
public IServiceDiscoveryProvider Get(ServiceProviderConfiguraion serviceConfig)
|
||||
public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig)
|
||||
{
|
||||
if (serviceConfig.UseServiceDiscovery)
|
||||
{
|
||||
|
@ -0,0 +1,74 @@
|
||||
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
|
||||
{
|
||||
public class AuthenticationOptionsCreatorTests
|
||||
{
|
||||
private AuthenticationOptionsCreator _authOptionsCreator;
|
||||
private FileReRoute _fileReRoute;
|
||||
private AuthenticationOptions _result;
|
||||
|
||||
public AuthenticationOptionsCreatorTests()
|
||||
{
|
||||
_authOptionsCreator = new AuthenticationOptionsCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_auth_options()
|
||||
{
|
||||
var fileReRoute = new FileReRoute()
|
||||
{
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
Provider = "Geoff",
|
||||
ProviderRootUrl = "http://www.bbc.co.uk/",
|
||||
ScopeName = "Laura",
|
||||
RequireHttps = true,
|
||||
AdditionalScopes = new List<string> {"cheese"},
|
||||
ScopeSecret = "secret"
|
||||
}
|
||||
};
|
||||
|
||||
var expected = new AuthenticationOptionsBuilder()
|
||||
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
||||
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.ProviderRootUrl)
|
||||
.WithScopeName(fileReRoute.AuthenticationOptions?.ScopeName)
|
||||
.WithRequireHttps(fileReRoute.AuthenticationOptions.RequireHttps)
|
||||
.WithAdditionalScopes(fileReRoute.AuthenticationOptions?.AdditionalScopes)
|
||||
.WithScopeSecret(fileReRoute.AuthenticationOptions?.ScopeSecret)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheFollowing(fileReRoute))
|
||||
.When(x => x.WhenICreateTheAuthenticationOptions())
|
||||
.Then(x => x.ThenTheFollowingIsReturned(expected))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(FileReRoute fileReRoute)
|
||||
{
|
||||
_fileReRoute = fileReRoute;
|
||||
}
|
||||
|
||||
private void WhenICreateTheAuthenticationOptions()
|
||||
{
|
||||
_result = _authOptionsCreator.Create(_fileReRoute);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(AuthenticationOptions expected)
|
||||
{
|
||||
_result.AdditionalScopes.ShouldBe(expected.AdditionalScopes);
|
||||
_result.Provider.ShouldBe(expected.Provider);
|
||||
_result.ProviderRootUrl.ShouldBe(expected.ProviderRootUrl);
|
||||
_result.RequireHttps.ShouldBe(expected.RequireHttps);
|
||||
_result.ScopeName.ShouldBe(expected.ScopeName);
|
||||
_result.ScopeSecret.ShouldBe(expected.ScopeSecret);
|
||||
}
|
||||
}
|
||||
}
|
110
test/Ocelot.UnitTests/Configuration/ClaimsToThingCreatorTests.cs
Normal file
110
test/Ocelot.UnitTests/Configuration/ClaimsToThingCreatorTests.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Configuration.Parser;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
public class ClaimsToThingCreatorTests
|
||||
{
|
||||
private readonly Mock<IClaimToThingConfigurationParser> _configParser;
|
||||
private Dictionary<string,string> _claimsToThings;
|
||||
private ClaimsToThingCreator _claimsToThingsCreator;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private List<ClaimToThing> _result;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
|
||||
public ClaimsToThingCreatorTests()
|
||||
{
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory
|
||||
.Setup(x => x.CreateLogger<ClaimsToThingCreator>())
|
||||
.Returns(_logger.Object);
|
||||
_configParser = new Mock<IClaimToThingConfigurationParser>();
|
||||
_claimsToThingsCreator = new ClaimsToThingCreator(_configParser.Object, _loggerFactory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_claims_to_things()
|
||||
{
|
||||
var userInput = new Dictionary<string,string>()
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"}
|
||||
};
|
||||
|
||||
var claimsToThing = new OkResponse<ClaimToThing>(new ClaimToThing("CustomerId", "CustomerId", "", 0));
|
||||
|
||||
this.Given(x => x.GivenTheFollowingDictionary(userInput))
|
||||
.And(x => x.GivenTheConfigHeaderExtractorReturns(claimsToThing))
|
||||
.When(x => x.WhenIGetTheThings())
|
||||
.Then(x => x.ThenTheConfigParserIsCalledCorrectly())
|
||||
.And(x => x.ThenClaimsToThingsAreReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_error_if_cannot_parse_claim_to_thing()
|
||||
{
|
||||
var userInput = new Dictionary<string,string>()
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"}
|
||||
};
|
||||
|
||||
var claimsToThing = new ErrorResponse<ClaimToThing>(It.IsAny<Error>());
|
||||
|
||||
this.Given(x => x.GivenTheFollowingDictionary(userInput))
|
||||
.And(x => x.GivenTheConfigHeaderExtractorReturns(claimsToThing))
|
||||
.When(x => x.WhenIGetTheThings())
|
||||
.Then(x => x.ThenTheConfigParserIsCalledCorrectly())
|
||||
.And(x => x.ThenNoClaimsToThingsAreReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheLoggerIsCalledCorrectly()
|
||||
{
|
||||
_logger
|
||||
.Verify(x => x.LogDebug(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenClaimsToThingsAreReturned()
|
||||
{
|
||||
_result.Count.ShouldBeGreaterThan(0);
|
||||
}
|
||||
private void GivenTheFollowingDictionary(Dictionary<string,string> claimsToThings)
|
||||
{
|
||||
_claimsToThings = claimsToThings;
|
||||
}
|
||||
|
||||
private void GivenTheConfigHeaderExtractorReturns(Response<ClaimToThing> expected)
|
||||
{
|
||||
_configParser
|
||||
.Setup(x => x.Extract(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(expected);
|
||||
}
|
||||
|
||||
private void ThenNoClaimsToThingsAreReturned()
|
||||
{
|
||||
_result.Count.ShouldBe(0);
|
||||
}
|
||||
|
||||
private void WhenIGetTheThings()
|
||||
{
|
||||
_result = _claimsToThingsCreator.Create(_claimsToThings);
|
||||
}
|
||||
|
||||
private void ThenTheConfigParserIsCalledCorrectly()
|
||||
{
|
||||
_configParser
|
||||
.Verify(x => x.Extract(_claimsToThings.First().Key, _claimsToThings.First().Value), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Configuration.Parser;
|
||||
using Ocelot.Configuration.Validator;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Requester.QoS;
|
||||
@ -23,7 +22,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
private readonly Mock<IConfigurationValidator> _validator;
|
||||
private Response<IOcelotConfiguration> _config;
|
||||
private FileConfiguration _fileConfiguration;
|
||||
private readonly Mock<IClaimToThingConfigurationParser> _configParser;
|
||||
private readonly Mock<ILogger<FileOcelotConfigurationCreator>> _logger;
|
||||
private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator;
|
||||
private readonly Mock<ILoadBalancerFactory> _loadBalancerFactory;
|
||||
@ -32,6 +30,14 @@ namespace Ocelot.UnitTests.Configuration
|
||||
private readonly Mock<IQoSProviderFactory> _qosProviderFactory;
|
||||
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
||||
private readonly Mock<IQoSProvider> _qosProvider;
|
||||
private Mock<IClaimsToThingCreator> _claimsToThingCreator;
|
||||
private Mock<IAuthenticationOptionsCreator> _authOptionsCreator;
|
||||
private Mock<IUpstreamTemplatePatternCreator> _upstreamTemplatePatternCreator;
|
||||
private Mock<IRequestIdKeyCreator> _requestIdKeyCreator;
|
||||
private Mock<IServiceProviderConfigurationCreator> _serviceProviderConfigCreator;
|
||||
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
||||
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
|
||||
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
|
||||
|
||||
public FileConfigurationCreatorTests()
|
||||
{
|
||||
@ -39,21 +45,35 @@ namespace Ocelot.UnitTests.Configuration
|
||||
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
||||
_qosProvider = new Mock<IQoSProvider>();
|
||||
_logger = new Mock<ILogger<FileOcelotConfigurationCreator>>();
|
||||
_configParser = new Mock<IClaimToThingConfigurationParser>();
|
||||
_validator = new Mock<IConfigurationValidator>();
|
||||
_fileConfig = new Mock<IOptions<FileConfiguration>>();
|
||||
_loadBalancerFactory = new Mock<ILoadBalancerFactory>();
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_loadBalancer = new Mock<ILoadBalancer>();
|
||||
_claimsToThingCreator = new Mock<IClaimsToThingCreator>();
|
||||
_authOptionsCreator = new Mock<IAuthenticationOptionsCreator>();
|
||||
_upstreamTemplatePatternCreator = new Mock<IUpstreamTemplatePatternCreator>();
|
||||
_requestIdKeyCreator = new Mock<IRequestIdKeyCreator>();
|
||||
_serviceProviderConfigCreator = new Mock<IServiceProviderConfigurationCreator>();
|
||||
_qosOptionsCreator = new Mock<IQoSOptionsCreator>();
|
||||
_fileReRouteOptionsCreator = new Mock<IReRouteOptionsCreator>();
|
||||
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
|
||||
|
||||
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
||||
_fileConfig.Object, _validator.Object, _configParser.Object, _logger.Object,
|
||||
_fileConfig.Object, _validator.Object, _logger.Object,
|
||||
_loadBalancerFactory.Object, _loadBalancerHouse.Object,
|
||||
_qosProviderFactory.Object, _qosProviderHouse.Object);
|
||||
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
|
||||
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
|
||||
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
|
||||
_rateLimitOptions.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_load_balancer()
|
||||
public void should_call_rate_limit_options_creator()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -68,16 +88,25 @@ namespace Ocelot.UnitTests.Configuration
|
||||
},
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.TheLoadBalancerFactoryIsCalledCorrectly())
|
||||
.And(x => x.ThenTheLoadBalancerHouseIsCalledCorrectly())
|
||||
.Then(x => x.ThenTheRateLimitOptionsCreatorIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_qos_provider()
|
||||
public void should_call_qos_options_creator()
|
||||
{
|
||||
var expected = new QoSOptionsBuilder()
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.WithTimeoutValue(1)
|
||||
.Build();
|
||||
|
||||
var serviceOptions = new ReRouteOptionsBuilder()
|
||||
.WithIsQos(true)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -98,16 +127,22 @@ namespace Ocelot.UnitTests.Configuration
|
||||
},
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(serviceOptions))
|
||||
.And(x => x.GivenTheQosProviderFactoryReturns())
|
||||
.And(x => x.GivenTheQosOptionsCreatorReturns(expected))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.TheQosProviderFactoryIsCalledCorrectly())
|
||||
.Then(x => x.ThenTheQosOptionsAre(expected))
|
||||
.And(x => x.TheQosProviderFactoryIsCalledCorrectly())
|
||||
.And(x => x.ThenTheQosProviderHouseIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_downstream_host()
|
||||
public void should_create_load_balancer()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -122,6 +157,35 @@ namespace Ocelot.UnitTests.Configuration
|
||||
},
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.TheLoadBalancerFactoryIsCalledCorrectly())
|
||||
.And(x => x.ThenTheLoadBalancerHouseIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_downstream_host()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamHost = "127.0.0.1",
|
||||
UpstreamPathTemplate = "/api/products/{productId}",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = "Get",
|
||||
}
|
||||
},
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
@ -130,7 +194,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
@ -139,6 +202,9 @@ namespace Ocelot.UnitTests.Configuration
|
||||
[Fact]
|
||||
public void should_use_downstream_scheme()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -153,6 +219,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
},
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
@ -161,7 +228,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
@ -170,6 +236,9 @@ namespace Ocelot.UnitTests.Configuration
|
||||
[Fact]
|
||||
public void should_use_service_discovery_for_downstream_service_host()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -193,6 +262,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
@ -200,8 +270,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder()
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder()
|
||||
.WithUseServiceDiscovery(true)
|
||||
.WithServiceDiscoveryProvider("consul")
|
||||
.WithServiceDiscoveryProviderHost("127.0.0.1")
|
||||
@ -215,6 +284,9 @@ namespace Ocelot.UnitTests.Configuration
|
||||
[Fact]
|
||||
public void should_not_use_service_discovery_for_downstream_host_url_when_no_service_name()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -229,6 +301,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
@ -236,8 +309,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder()
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder()
|
||||
.WithUseServiceDiscovery(false)
|
||||
.Build())
|
||||
.Build()
|
||||
@ -246,8 +318,11 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_reroute_case_sensitivity_value()
|
||||
public void should_call_template_pattern_creator_correctly()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -262,6 +337,8 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.And(x => x.GivenTheUpstreamTemplatePatternCreatorReturns("(?i)/api/products/.*/$"))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
@ -276,67 +353,11 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_upstream_template_pattern_to_ignore_case_sensitivity()
|
||||
public void should_call_request_id_creator()
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = "Get"
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
}
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
[Fact]
|
||||
public void should_set_upstream_template_pattern_to_respect_case_sensitivity()
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = "Get",
|
||||
ReRouteIsCaseSensitive = true
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_global_request_id_key()
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -355,6 +376,8 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.And(x => x.GivenTheRequestIdCreatorReturns("blahhhh"))
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
@ -362,46 +385,20 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
||||
.WithRequestIdKey("blahhhh")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_anything_to_end_of_string()
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = "Get",
|
||||
ReRouteIsCaseSensitive = true
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.And(x => x.ThenTheRequestIdKeyCreatorIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_with_headers_to_extract()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.WithIsAuthenticated(true)
|
||||
.Build();
|
||||
|
||||
var authenticationOptions = new AuthenticationOptionsBuilder()
|
||||
.WithProvider("IdentityServer")
|
||||
.WithProviderRootUrl("http://localhost:51888")
|
||||
@ -417,7 +414,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
||||
.WithAuthenticationOptions(authenticationOptions)
|
||||
.WithClaimsToHeaders(new List<ClaimToThing>
|
||||
{
|
||||
@ -453,24 +449,24 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheConfigHeaderExtractorReturns(new ClaimToThing("CustomerId", "CustomerId", "", 0)))
|
||||
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.And(x => x.GivenTheClaimsToThingCreatorReturns(new List<ClaimToThing>{new ClaimToThing("CustomerId", "CustomerId", "", 0)}))
|
||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(expected))
|
||||
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
||||
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheConfigHeaderExtractorReturns(ClaimToThing expected)
|
||||
{
|
||||
_configParser
|
||||
.Setup(x => x.Extract(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(new OkResponse<ClaimToThing>(expected));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_with_authentication_properties()
|
||||
{
|
||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||
.WithIsAuthenticated(true)
|
||||
.Build();
|
||||
|
||||
var authenticationOptions = new AuthenticationOptionsBuilder()
|
||||
.WithProvider("IdentityServer")
|
||||
.WithProviderRootUrl("http://localhost:51888")
|
||||
@ -486,7 +482,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
||||
.WithAuthenticationOptions(authenticationOptions)
|
||||
.Build()
|
||||
};
|
||||
@ -514,101 +509,27 @@ namespace Ocelot.UnitTests.Configuration
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(expected))
|
||||
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
||||
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_more_than_one_placeholder()
|
||||
private void GivenTheFollowingOptionsAreReturned(ReRouteOptions fileReRouteOptions)
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = "Get",
|
||||
ReRouteIsCaseSensitive = true
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}/variants/{variantId}")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/variants/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
_fileReRouteOptionsCreator
|
||||
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||
.Returns(fileReRouteOptions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_more_than_one_placeholder_with_trailing_slash()
|
||||
private void ThenTheRateLimitOptionsCreatorIsCalledCorrectly()
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}/",
|
||||
DownstreamPathTemplate = "/products/{productId}",
|
||||
UpstreamHttpMethod = "Get",
|
||||
ReRouteIsCaseSensitive = true
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}/variants/{variantId}/")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("/api/products/.*/variants/.*/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_to_end_of_string()
|
||||
{
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/",
|
||||
DownstreamPathTemplate = "/api/products/",
|
||||
UpstreamHttpMethod = "Get",
|
||||
ReRouteIsCaseSensitive = true
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheConfigIsValid())
|
||||
.When(x => x.WhenICreateTheConfig())
|
||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/products/")
|
||||
.WithUpstreamPathTemplate("/")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithUpstreamTemplatePattern("^/$")
|
||||
.Build()
|
||||
}))
|
||||
.BDDfy();
|
||||
_rateLimitOptions
|
||||
.Verify(x => x.Create(It.IsAny<FileReRoute>(), It.IsAny<FileGlobalConfiguration>(), It.IsAny<bool>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheConfigIsValid()
|
||||
@ -642,6 +563,25 @@ namespace Ocelot.UnitTests.Configuration
|
||||
result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod);
|
||||
result.UpstreamPathTemplate.Value.ShouldBe(expected.UpstreamPathTemplate.Value);
|
||||
result.UpstreamTemplatePattern.ShouldBe(expected.UpstreamTemplatePattern);
|
||||
result.ClaimsToClaims.Count.ShouldBe(expected.ClaimsToClaims.Count);
|
||||
result.ClaimsToHeaders.Count.ShouldBe(expected.ClaimsToHeaders.Count);
|
||||
result.ClaimsToQueries.Count.ShouldBe(expected.ClaimsToQueries.Count);
|
||||
result.RequestIdKey.ShouldBe(expected.RequestIdKey);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenTheServiceConfigurationIs(ServiceProviderConfiguration expected)
|
||||
{
|
||||
for (int i = 0; i < _config.Data.ReRoutes.Count; i++)
|
||||
{
|
||||
var result = _config.Data.ReRoutes[i];
|
||||
result.ServiceProviderConfiguraion.DownstreamHost.ShouldBe(expected.DownstreamHost);
|
||||
result.ServiceProviderConfiguraion.DownstreamPort.ShouldBe(expected.DownstreamPort);
|
||||
result.ServiceProviderConfiguraion.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider);
|
||||
result.ServiceProviderConfiguraion.ServiceName.ShouldBe(expected.ServiceName);
|
||||
result.ServiceProviderConfiguraion.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost);
|
||||
result.ServiceProviderConfiguraion.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort);
|
||||
}
|
||||
}
|
||||
|
||||
@ -699,5 +639,60 @@ namespace Ocelot.UnitTests.Configuration
|
||||
_qosProviderHouse
|
||||
.Verify(x => x.Add(It.IsAny<string>(), _qosProvider.Object), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheClaimsToThingCreatorReturns(List<ClaimToThing> claimsToThing)
|
||||
{
|
||||
_claimsToThingCreator
|
||||
.Setup(x => x.Create(_fileConfiguration.ReRoutes[0].AddHeadersToRequest))
|
||||
.Returns(claimsToThing);
|
||||
}
|
||||
|
||||
private void GivenTheAuthOptionsCreatorReturns(AuthenticationOptions authOptions)
|
||||
{
|
||||
_authOptionsCreator
|
||||
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||
.Returns(authOptions);
|
||||
}
|
||||
|
||||
private void ThenTheAuthOptionsCreatorIsCalledCorrectly()
|
||||
{
|
||||
_authOptionsCreator
|
||||
.Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheUpstreamTemplatePatternCreatorReturns(string pattern)
|
||||
{
|
||||
_upstreamTemplatePatternCreator
|
||||
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||
.Returns(pattern);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdKeyCreatorIsCalledCorrectly()
|
||||
{
|
||||
_requestIdKeyCreator
|
||||
.Verify(x => x.Create(_fileConfiguration.ReRoutes[0], _fileConfiguration.GlobalConfiguration), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheRequestIdCreatorReturns(string requestId)
|
||||
{
|
||||
_requestIdKeyCreator
|
||||
.Setup(x => x.Create(It.IsAny<FileReRoute>(), It.IsAny<FileGlobalConfiguration>()))
|
||||
.Returns(requestId);
|
||||
}
|
||||
|
||||
private void GivenTheQosOptionsCreatorReturns(QoSOptions qosOptions)
|
||||
{
|
||||
_qosOptionsCreator
|
||||
.Setup(x => x.Create(_fileConfiguration.ReRoutes[0]))
|
||||
.Returns(qosOptions);
|
||||
}
|
||||
|
||||
private void ThenTheQosOptionsAre(QoSOptions qosOptions)
|
||||
{
|
||||
_config.Data.ReRoutes[0].QosOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
|
||||
|
||||
_config.Data.ReRoutes[0].QosOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
|
||||
_config.Data.ReRoutes[0].QosOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
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
|
||||
{
|
||||
public class QoSOptionsCreatorTests
|
||||
{
|
||||
private QoSOptionsCreator _creator;
|
||||
private FileReRoute _fileReRoute;
|
||||
private QoSOptions _result;
|
||||
|
||||
public QoSOptionsCreatorTests()
|
||||
{
|
||||
_creator = new QoSOptionsCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_qos_options()
|
||||
{
|
||||
var reRoute = new FileReRoute
|
||||
{
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
DurationOfBreak = 1,
|
||||
TimeoutValue = 1
|
||||
}
|
||||
};
|
||||
var expected = new QoSOptionsBuilder()
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.WithTimeoutValue(1)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheFollowingIsReturned(expected))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowingReRoute(FileReRoute fileReRoute)
|
||||
{
|
||||
_fileReRoute = fileReRoute;
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Create(_fileReRoute);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(QoSOptions expected)
|
||||
{
|
||||
_result.DurationOfBreak.ShouldBe(expected.DurationOfBreak);
|
||||
_result.ExceptionsAllowedBeforeBreaking.ShouldBe(expected.ExceptionsAllowedBeforeBreaking);
|
||||
_result.TimeoutValue.ShouldBe(expected.TimeoutValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
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
|
||||
{
|
||||
public class RateLimitOptionsCreatorTests
|
||||
{
|
||||
private FileReRoute _fileReRoute;
|
||||
private FileGlobalConfiguration _fileGlobalConfig;
|
||||
private bool _enabled;
|
||||
private RateLimitOptionsCreator _creator;
|
||||
private RateLimitOptions _result;
|
||||
|
||||
public RateLimitOptionsCreatorTests()
|
||||
{
|
||||
_creator = new RateLimitOptionsCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_rate_limit_options()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
RateLimitOptions = new FileRateLimitRule
|
||||
{
|
||||
ClientWhitelist = new List<string>(),
|
||||
Period = "Period",
|
||||
Limit = 1,
|
||||
PeriodTimespan = 1,
|
||||
EnableRateLimiting = true
|
||||
}
|
||||
};
|
||||
var fileGlobalConfig = new FileGlobalConfiguration
|
||||
{
|
||||
RateLimitOptions = new FileRateLimitOptions
|
||||
{
|
||||
ClientIdHeader = "ClientIdHeader",
|
||||
DisableRateLimitHeaders = true,
|
||||
QuotaExceededMessage = "QuotaExceededMessage",
|
||||
RateLimitCounterPrefix = "RateLimitCounterPrefix",
|
||||
HttpStatusCode = 200
|
||||
}
|
||||
};
|
||||
var expected = new RateLimitOptionsBuilder()
|
||||
.WithClientIdHeader("ClientIdHeader")
|
||||
.WithClientWhiteList(fileReRoute.RateLimitOptions.ClientWhitelist)
|
||||
.WithDisableRateLimitHeaders(true)
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithHttpStatusCode(200)
|
||||
.WithQuotaExceededMessage("QuotaExceededMessage")
|
||||
.WithRateLimitCounterPrefix("RateLimitCounterPrefix")
|
||||
.WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
|
||||
TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan),
|
||||
fileReRoute.RateLimitOptions.Limit))
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.And(x => x.GivenTheFollowingFileGlobalConfig(fileGlobalConfig))
|
||||
.And(x => x.GivenRateLimitingIsEnabled())
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheFollowingIsReturned(expected))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute)
|
||||
{
|
||||
_fileReRoute = fileReRoute;
|
||||
}
|
||||
|
||||
private void GivenTheFollowingFileGlobalConfig(FileGlobalConfiguration fileGlobalConfig)
|
||||
{
|
||||
_fileGlobalConfig = fileGlobalConfig;
|
||||
}
|
||||
|
||||
private void GivenRateLimitingIsEnabled()
|
||||
{
|
||||
_enabled = true;
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Create(_fileReRoute, _fileGlobalConfig, _enabled);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(RateLimitOptions expected)
|
||||
{
|
||||
_result.ClientIdHeader.ShouldBe(expected.ClientIdHeader);
|
||||
_result.ClientWhitelist.ShouldBe(expected.ClientWhitelist);
|
||||
_result.DisableRateLimitHeaders.ShouldBe(expected.DisableRateLimitHeaders);
|
||||
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
|
||||
_result.HttpStatusCode.ShouldBe(expected.HttpStatusCode);
|
||||
_result.QuotaExceededMessage.ShouldBe(expected.QuotaExceededMessage);
|
||||
_result.RateLimitCounterPrefix.ShouldBe(expected.RateLimitCounterPrefix);
|
||||
_result.RateLimitRule.Limit.ShouldBe(expected.RateLimitRule.Limit);
|
||||
_result.RateLimitRule.Period.ShouldBe(expected.RateLimitRule.Period);
|
||||
_result.RateLimitRule.PeriodTimespan.Ticks.ShouldBe(expected.RateLimitRule.PeriodTimespan.Ticks);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
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
|
||||
{
|
||||
public class ReRouteOptionsCreatorTests
|
||||
{
|
||||
private ReRouteOptionsCreator _creator;
|
||||
private FileReRoute _reRoute;
|
||||
private ReRouteOptions _result;
|
||||
|
||||
public ReRouteOptionsCreatorTests()
|
||||
{
|
||||
_creator = new ReRouteOptionsCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_re_route_options()
|
||||
{
|
||||
var reRoute = new FileReRoute
|
||||
{
|
||||
RateLimitOptions = new FileRateLimitRule
|
||||
{
|
||||
EnableRateLimiting = true
|
||||
},
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
TimeoutValue = 1
|
||||
},
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
Provider = "IdentityServer"
|
||||
},
|
||||
RouteClaimsRequirement = new Dictionary<string, string>()
|
||||
{
|
||||
{"",""}
|
||||
},
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 1
|
||||
}
|
||||
};
|
||||
|
||||
var expected = new ReRouteOptionsBuilder()
|
||||
.WithIsAuthenticated(true)
|
||||
.WithIsAuthorised(true)
|
||||
.WithIsCached(true)
|
||||
.WithIsQos(true)
|
||||
.WithRateLimiting(true)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheFollowing(reRoute))
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheFollowingIsReturned(expected))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(FileReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Create(_reRoute);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(ReRouteOptions expected)
|
||||
{
|
||||
_result.IsAuthenticated.ShouldBe(expected.IsAuthenticated);
|
||||
_result.IsAuthorised.ShouldBe(expected.IsAuthorised);
|
||||
_result.IsQos.ShouldBe(expected.IsQos);
|
||||
_result.IsCached.ShouldBe(expected.IsCached);
|
||||
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Configuration.File;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
public class RequestIdKeyCreatorTests
|
||||
{
|
||||
private FileReRoute _fileReRoute;
|
||||
private FileGlobalConfiguration _fileGlobalConfig;
|
||||
private string _result;
|
||||
private RequestIdKeyCreator _creator;
|
||||
|
||||
public RequestIdKeyCreatorTests()
|
||||
{
|
||||
_creator = new RequestIdKeyCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_global_configuration()
|
||||
{
|
||||
var reRoute = new FileReRoute();
|
||||
var globalConfig = new FileGlobalConfiguration
|
||||
{
|
||||
RequestIdKey = "cheese"
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
||||
.And(x => x.GivenTheFollowingGlobalConfig(globalConfig))
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("cheese"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_re_route_specific()
|
||||
{
|
||||
var reRoute = new FileReRoute
|
||||
{
|
||||
RequestIdKey = "cheese"
|
||||
};
|
||||
var globalConfig = new FileGlobalConfiguration();
|
||||
|
||||
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
||||
.And(x => x.GivenTheFollowingGlobalConfig(globalConfig))
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("cheese"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_global_cofiguration_over_re_route_specific()
|
||||
{
|
||||
var reRoute = new FileReRoute
|
||||
{
|
||||
RequestIdKey = "cheese"
|
||||
}; var globalConfig = new FileGlobalConfiguration
|
||||
{
|
||||
RequestIdKey = "cheese"
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
||||
.And(x => x.GivenTheFollowingGlobalConfig(globalConfig))
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("cheese"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowingReRoute(FileReRoute fileReRoute)
|
||||
{
|
||||
_fileReRoute = fileReRoute;
|
||||
}
|
||||
|
||||
private void GivenTheFollowingGlobalConfig(FileGlobalConfiguration globalConfig)
|
||||
{
|
||||
_fileGlobalConfig = globalConfig;
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Create(_fileReRoute, _fileGlobalConfig);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(string expected)
|
||||
{
|
||||
_result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
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
|
||||
{
|
||||
public class ServiceProviderCreatorTests
|
||||
{
|
||||
private ServiceProviderConfigurationCreator _creator;
|
||||
private FileReRoute _reRoute;
|
||||
private FileGlobalConfiguration _globalConfig;
|
||||
private ServiceProviderConfiguration _result;
|
||||
|
||||
public ServiceProviderCreatorTests()
|
||||
{
|
||||
_creator = new ServiceProviderConfigurationCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_provider_config()
|
||||
{
|
||||
var reRoute = new FileReRoute();
|
||||
|
||||
var globalConfig = new FileGlobalConfiguration
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
|
||||
{
|
||||
Provider = "consul",
|
||||
Host = "127.0.0.1",
|
||||
Port = 1234
|
||||
}
|
||||
};
|
||||
|
||||
var expected = new ServiceProviderConfigurationBuilder()
|
||||
.WithServiceDiscoveryProvider("consul")
|
||||
.WithServiceDiscoveryProviderHost("127.0.0.1")
|
||||
.WithServiceDiscoveryProviderPort(1234)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
||||
.And(x => x.GivenTheFollowingGlobalConfig(globalConfig))
|
||||
.When(x => x.WhenICreate())
|
||||
.Then(x => x.ThenTheConfigIs(expected))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowingReRoute(FileReRoute fileReRoute)
|
||||
{
|
||||
_reRoute = fileReRoute;
|
||||
}
|
||||
|
||||
private void GivenTheFollowingGlobalConfig(FileGlobalConfiguration fileGlobalConfig)
|
||||
{
|
||||
_globalConfig = fileGlobalConfig;
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Create(_reRoute, _globalConfig);
|
||||
}
|
||||
|
||||
private void ThenTheConfigIs(ServiceProviderConfiguration expected)
|
||||
{
|
||||
_result.DownstreamHost.ShouldBe(expected.DownstreamHost);
|
||||
_result.DownstreamPort.ShouldBe(expected.DownstreamPort);
|
||||
_result.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider);
|
||||
_result.ServiceName.ShouldBe(expected.ServiceName);
|
||||
_result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost);
|
||||
_result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Configuration.File;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
public class UpstreamTemplatePatternCreatorTests
|
||||
{
|
||||
private FileReRoute _fileReRoute;
|
||||
private UpstreamTemplatePatternCreator _creator;
|
||||
private string _result;
|
||||
|
||||
public UpstreamTemplatePatternCreatorTests()
|
||||
{
|
||||
_creator = new UpstreamTemplatePatternCreator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_upstream_template_pattern_to_ignore_case_sensitivity()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/PRODUCTS/{productId}",
|
||||
ReRouteIsCaseSensitive = false
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.When(x => x.WhenICreateTheTemplatePattern())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("(?i)/PRODUCTS/.*/$"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_upstream_template_pattern_to_respect_case_sensitivity()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/PRODUCTS/{productId}",
|
||||
ReRouteIsCaseSensitive = true
|
||||
};
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.When(x => x.WhenICreateTheTemplatePattern())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("/PRODUCTS/.*/$"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_anything_to_end_of_string()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}",
|
||||
ReRouteIsCaseSensitive = true
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.When(x => x.WhenICreateTheTemplatePattern())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("/api/products/.*/$"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_more_than_one_placeholder()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}",
|
||||
ReRouteIsCaseSensitive = true
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.When(x => x.WhenICreateTheTemplatePattern())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("/api/products/.*/variants/.*/$"))
|
||||
.BDDfy();
|
||||
}
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_more_than_one_placeholder_with_trailing_slash()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}/",
|
||||
ReRouteIsCaseSensitive = true
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.When(x => x.WhenICreateTheTemplatePattern())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("/api/products/.*/variants/.*/$"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_template_pattern_that_matches_to_end_of_string()
|
||||
{
|
||||
var fileReRoute = new FileReRoute
|
||||
{
|
||||
UpstreamPathTemplate = "/"
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||
.When(x => x.WhenICreateTheTemplatePattern())
|
||||
.Then(x => x.ThenTheFollowingIsReturned("^/$"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute)
|
||||
{
|
||||
_fileReRoute = fileReRoute;
|
||||
}
|
||||
|
||||
private void WhenICreateTheTemplatePattern()
|
||||
{
|
||||
_result = _creator.Create(_fileReRoute);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(string expected)
|
||||
{
|
||||
_result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.File;
|
||||
|
@ -28,7 +28,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
public void should_return_no_load_balancer()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder().Build())
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.Build();
|
||||
|
||||
@ -45,7 +45,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("RoundRobin")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder().Build())
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
@ -61,7 +61,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("LeastConnection")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder().Build())
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
@ -77,7 +77,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithLoadBalancer("RoundRobin")
|
||||
.WithUpstreamHttpMethod("Get")
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder().Build())
|
||||
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
@ -90,14 +90,14 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private void GivenTheServiceProviderFactoryReturns()
|
||||
{
|
||||
_serviceProviderFactory
|
||||
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguraion>()))
|
||||
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>()))
|
||||
.Returns(_serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void ThenTheServiceProviderIsCalledCorrectly()
|
||||
{
|
||||
_serviceProviderFactory
|
||||
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguraion>()), Times.Once);
|
||||
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenAReRoute(ReRoute reRoute)
|
||||
|
@ -9,7 +9,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
|
||||
{
|
||||
public class ServiceProviderFactoryTests
|
||||
{
|
||||
private ServiceProviderConfiguraion _serviceConfig;
|
||||
private ServiceProviderConfiguration _serviceConfig;
|
||||
private IServiceDiscoveryProvider _result;
|
||||
private readonly ServiceDiscoveryProviderFactory _factory;
|
||||
|
||||
@ -21,7 +21,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
|
||||
[Fact]
|
||||
public void should_return_no_service_provider()
|
||||
{
|
||||
var serviceConfig = new ServiceProviderConfiguraionBuilder()
|
||||
var serviceConfig = new ServiceProviderConfigurationBuilder()
|
||||
.WithDownstreamHost("127.0.0.1")
|
||||
.WithDownstreamPort(80)
|
||||
.WithUseServiceDiscovery(false)
|
||||
@ -36,7 +36,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
|
||||
[Fact]
|
||||
public void should_return_consul_service_provider()
|
||||
{
|
||||
var serviceConfig = new ServiceProviderConfiguraionBuilder()
|
||||
var serviceConfig = new ServiceProviderConfigurationBuilder()
|
||||
.WithServiceName("product")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.WithServiceDiscoveryProvider("Consul")
|
||||
@ -48,7 +48,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheReRoute(ServiceProviderConfiguraion serviceConfig)
|
||||
private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig)
|
||||
{
|
||||
_serviceConfig = serviceConfig;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user