mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
refactoring ocelot config creation process
This commit is contained in:
parent
1d216f6863
commit
c85ea41951
@ -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,38 @@ namespace Ocelot.Configuration.Creator
|
|||||||
{
|
{
|
||||||
private readonly IOptions<FileConfiguration> _options;
|
private readonly IOptions<FileConfiguration> _options;
|
||||||
private readonly IConfigurationValidator _configurationValidator;
|
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 ILogger<FileOcelotConfigurationCreator> _logger;
|
||||||
private readonly ILoadBalancerFactory _loadBalanceFactory;
|
private readonly ILoadBalancerFactory _loadBalanceFactory;
|
||||||
private readonly ILoadBalancerHouse _loadBalancerHouse;
|
private readonly ILoadBalancerHouse _loadBalancerHouse;
|
||||||
private readonly IQoSProviderFactory _qoSProviderFactory;
|
private readonly IQoSProviderFactory _qoSProviderFactory;
|
||||||
private readonly IQosProviderHouse _qosProviderHouse;
|
private readonly IQosProviderHouse _qosProviderHouse;
|
||||||
|
private readonly IClaimsToThingCreator _claimsToThingCreator;
|
||||||
|
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
|
||||||
|
private IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
|
||||||
|
|
||||||
public FileOcelotConfigurationCreator(
|
public FileOcelotConfigurationCreator(
|
||||||
IOptions<FileConfiguration> options,
|
IOptions<FileConfiguration> options,
|
||||||
IConfigurationValidator configurationValidator,
|
IConfigurationValidator configurationValidator,
|
||||||
IClaimToThingConfigurationParser claimToThingConfigurationParser,
|
|
||||||
ILogger<FileOcelotConfigurationCreator> logger,
|
ILogger<FileOcelotConfigurationCreator> logger,
|
||||||
ILoadBalancerFactory loadBalancerFactory,
|
ILoadBalancerFactory loadBalancerFactory,
|
||||||
ILoadBalancerHouse loadBalancerHouse,
|
ILoadBalancerHouse loadBalancerHouse,
|
||||||
IQoSProviderFactory qoSProviderFactory,
|
IQoSProviderFactory qoSProviderFactory,
|
||||||
IQosProviderHouse qosProviderHouse)
|
IQosProviderHouse qosProviderHouse,
|
||||||
|
IClaimsToThingCreator claimsToThingCreator,
|
||||||
|
IAuthenticationOptionsCreator authOptionsCreator,
|
||||||
|
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator)
|
||||||
{
|
{
|
||||||
|
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
||||||
|
_authOptionsCreator = authOptionsCreator;
|
||||||
_loadBalanceFactory = loadBalancerFactory;
|
_loadBalanceFactory = loadBalancerFactory;
|
||||||
_loadBalancerHouse = loadBalancerHouse;
|
_loadBalancerHouse = loadBalancerHouse;
|
||||||
_qoSProviderFactory = qoSProviderFactory;
|
_qoSProviderFactory = qoSProviderFactory;
|
||||||
_qosProviderHouse = qosProviderHouse;
|
_qosProviderHouse = qosProviderHouse;
|
||||||
_options = options;
|
_options = options;
|
||||||
_configurationValidator = configurationValidator;
|
_configurationValidator = configurationValidator;
|
||||||
_claimToThingConfigurationParser = claimToThingConfigurationParser;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_claimsToThingCreator = claimsToThingCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Response<IOcelotConfiguration>> Create()
|
public async Task<Response<IOcelotConfiguration>> Create()
|
||||||
@ -107,19 +109,19 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
var reRouteKey = BuildReRouteKey(fileReRoute);
|
var reRouteKey = BuildReRouteKey(fileReRoute);
|
||||||
|
|
||||||
var upstreamTemplatePattern = BuildUpstreamTemplatePattern(fileReRoute);
|
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var isQos = IsQoS(fileReRoute);
|
var isQos = IsQoS(fileReRoute);
|
||||||
|
|
||||||
var serviceProviderConfiguration = BuildServiceProviderConfiguration(fileReRoute, globalConfiguration);
|
var serviceProviderConfiguration = BuildServiceProviderConfiguration(fileReRoute, globalConfiguration);
|
||||||
|
|
||||||
var authOptionsForRoute = BuildAuthenticationOptions(fileReRoute);
|
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var claimsToHeaders = BuildAddThingsToRequest(fileReRoute.AddHeadersToRequest);
|
var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
|
||||||
|
|
||||||
var claimsToClaims = BuildAddThingsToRequest(fileReRoute.AddClaimsToRequest);
|
var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
|
||||||
|
|
||||||
var claimsToQueries = BuildAddThingsToRequest(fileReRoute.AddQueriesToRequest);
|
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
|
||||||
|
|
||||||
var qosOptions = BuildQoSOptions(fileReRoute);
|
var qosOptions = BuildQoSOptions(fileReRoute);
|
||||||
|
|
||||||
@ -153,6 +155,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithEnableRateLimiting(enableRateLimiting)
|
.WithEnableRateLimiting(enableRateLimiting)
|
||||||
.WithRateLimitOptions(rateLimitOption)
|
.WithRateLimitOptions(rateLimitOption)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
await SetupLoadBalancer(reRoute);
|
await SetupLoadBalancer(reRoute);
|
||||||
SetupQosProvider(reRoute);
|
SetupQosProvider(reRoute);
|
||||||
return reRoute;
|
return reRoute;
|
||||||
@ -225,18 +228,6 @@ namespace Ocelot.Configuration.Creator
|
|||||||
return loadBalancerKey;
|
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)
|
private async Task SetupLoadBalancer(ReRoute reRoute)
|
||||||
{
|
{
|
||||||
var loadBalancer = await _loadBalanceFactory.Get(reRoute);
|
var loadBalancer = await _loadBalanceFactory.Get(reRoute);
|
||||||
@ -267,63 +258,6 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.Build();
|
.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)
|
private bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||||
{
|
{
|
||||||
return upstreamTemplate[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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
namespace Ocelot.Configuration.Creator
|
||||||
|
{
|
||||||
|
public interface IUpstreamTemplatePatternCreator
|
||||||
|
{
|
||||||
|
string Create(FileReRoute reRoute);
|
||||||
|
}
|
||||||
|
}
|
@ -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] == '{';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -60,6 +60,9 @@ namespace Ocelot.DependencyInjection
|
|||||||
services.AddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
|
services.AddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
|
||||||
services.AddSingleton<IConfigurationValidator, FileConfigurationValidator>();
|
services.AddSingleton<IConfigurationValidator, FileConfigurationValidator>();
|
||||||
services.AddSingleton<IBaseUrlFinder, BaseUrlFinder>();
|
services.AddSingleton<IBaseUrlFinder, BaseUrlFinder>();
|
||||||
|
services.AddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>();
|
||||||
|
services.AddSingleton<IAuthenticationOptionsCreator, AuthenticationOptionsCreator>();
|
||||||
|
services.AddSingleton<IUpstreamTemplatePatternCreator, UpstreamTemplatePatternCreator>();
|
||||||
|
|
||||||
var identityServerConfiguration = IdentityServerConfigurationCreator.GetIdentityServerConfiguration();
|
var identityServerConfiguration = IdentityServerConfigurationCreator.GetIdentityServerConfiguration();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
private readonly Mock<IConfigurationValidator> _validator;
|
private readonly Mock<IConfigurationValidator> _validator;
|
||||||
private Response<IOcelotConfiguration> _config;
|
private Response<IOcelotConfiguration> _config;
|
||||||
private FileConfiguration _fileConfiguration;
|
private FileConfiguration _fileConfiguration;
|
||||||
private readonly Mock<IClaimToThingConfigurationParser> _configParser;
|
|
||||||
private readonly Mock<ILogger<FileOcelotConfigurationCreator>> _logger;
|
private readonly Mock<ILogger<FileOcelotConfigurationCreator>> _logger;
|
||||||
private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator;
|
private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator;
|
||||||
private readonly Mock<ILoadBalancerFactory> _loadBalancerFactory;
|
private readonly Mock<ILoadBalancerFactory> _loadBalancerFactory;
|
||||||
@ -32,6 +31,9 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
private readonly Mock<IQoSProviderFactory> _qosProviderFactory;
|
private readonly Mock<IQoSProviderFactory> _qosProviderFactory;
|
||||||
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
||||||
private readonly Mock<IQoSProvider> _qosProvider;
|
private readonly Mock<IQoSProvider> _qosProvider;
|
||||||
|
private Mock<IClaimsToThingCreator> _claimsToThingCreator;
|
||||||
|
private Mock<IAuthenticationOptionsCreator> _authOptionsCreator;
|
||||||
|
private Mock<IUpstreamTemplatePatternCreator> _upstreamTemplatePatternCreator;
|
||||||
|
|
||||||
public FileConfigurationCreatorTests()
|
public FileConfigurationCreatorTests()
|
||||||
{
|
{
|
||||||
@ -39,16 +41,20 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
||||||
_qosProvider = new Mock<IQoSProvider>();
|
_qosProvider = new Mock<IQoSProvider>();
|
||||||
_logger = new Mock<ILogger<FileOcelotConfigurationCreator>>();
|
_logger = new Mock<ILogger<FileOcelotConfigurationCreator>>();
|
||||||
_configParser = new Mock<IClaimToThingConfigurationParser>();
|
|
||||||
_validator = new Mock<IConfigurationValidator>();
|
_validator = new Mock<IConfigurationValidator>();
|
||||||
_fileConfig = new Mock<IOptions<FileConfiguration>>();
|
_fileConfig = new Mock<IOptions<FileConfiguration>>();
|
||||||
_loadBalancerFactory = new Mock<ILoadBalancerFactory>();
|
_loadBalancerFactory = new Mock<ILoadBalancerFactory>();
|
||||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||||
_loadBalancer = new Mock<ILoadBalancer>();
|
_loadBalancer = new Mock<ILoadBalancer>();
|
||||||
|
_claimsToThingCreator = new Mock<IClaimsToThingCreator>();
|
||||||
|
_authOptionsCreator = new Mock<IAuthenticationOptionsCreator>();
|
||||||
|
_upstreamTemplatePatternCreator = new Mock<IUpstreamTemplatePatternCreator>();
|
||||||
|
|
||||||
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
||||||
_fileConfig.Object, _validator.Object, _configParser.Object, _logger.Object,
|
_fileConfig.Object, _validator.Object, _logger.Object,
|
||||||
_loadBalancerFactory.Object, _loadBalancerHouse.Object,
|
_loadBalancerFactory.Object, _loadBalancerHouse.Object,
|
||||||
_qosProviderFactory.Object, _qosProviderHouse.Object);
|
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
|
||||||
|
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -130,7 +136,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
|
||||||
.Build()
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -161,7 +166,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
|
||||||
.Build()
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -200,7 +204,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
|
||||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder()
|
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder()
|
||||||
.WithUseServiceDiscovery(true)
|
.WithUseServiceDiscovery(true)
|
||||||
.WithServiceDiscoveryProvider("consul")
|
.WithServiceDiscoveryProvider("consul")
|
||||||
@ -236,7 +239,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
|
|
||||||
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder()
|
.WithServiceProviderConfiguraion(new ServiceProviderConfiguraionBuilder()
|
||||||
.WithUseServiceDiscovery(false)
|
.WithUseServiceDiscovery(false)
|
||||||
.Build())
|
.Build())
|
||||||
@ -246,7 +248,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_use_reroute_case_sensitivity_value()
|
public void should_call_template_pattern_creator_correctly()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
{
|
{
|
||||||
@ -262,6 +264,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.And(x => x.GivenTheConfigIsValid())
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
|
.And(x => x.GivenTheUpstreamTemplatePatternCreatorReturns("(?i)/api/products/.*/$"))
|
||||||
.When(x => x.WhenICreateTheConfig())
|
.When(x => x.WhenICreateTheConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
{
|
{
|
||||||
@ -275,65 +278,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_set_upstream_template_pattern_to_ignore_case_sensitivity()
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
[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]
|
[Fact]
|
||||||
public void should_set_global_request_id_key()
|
public void should_set_global_request_id_key()
|
||||||
{
|
{
|
||||||
@ -362,43 +306,12 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
|
||||||
.WithRequestIdKey("blahhhh")
|
.WithRequestIdKey("blahhhh")
|
||||||
.Build()
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.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()
|
|
||||||
}))
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_create_with_headers_to_extract()
|
public void should_create_with_headers_to_extract()
|
||||||
{
|
{
|
||||||
@ -417,7 +330,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
|
||||||
.WithAuthenticationOptions(authenticationOptions)
|
.WithAuthenticationOptions(authenticationOptions)
|
||||||
.WithClaimsToHeaders(new List<ClaimToThing>
|
.WithClaimsToHeaders(new List<ClaimToThing>
|
||||||
{
|
{
|
||||||
@ -453,20 +365,17 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.And(x => x.GivenTheConfigIsValid())
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
.And(x => x.GivenTheConfigHeaderExtractorReturns(new ClaimToThing("CustomerId", "CustomerId", "", 0)))
|
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
||||||
|
.And(x => x.GivenTheClaimsToThingCreatorReturns(new List<ClaimToThing>{new ClaimToThing("CustomerId", "CustomerId", "", 0)}))
|
||||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||||
.When(x => x.WhenICreateTheConfig())
|
.When(x => x.WhenICreateTheConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(expected))
|
.Then(x => x.ThenTheReRoutesAre(expected))
|
||||||
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
||||||
|
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheConfigHeaderExtractorReturns(ClaimToThing expected)
|
|
||||||
{
|
|
||||||
_configParser
|
|
||||||
.Setup(x => x.Extract(It.IsAny<string>(), It.IsAny<string>()))
|
|
||||||
.Returns(new OkResponse<ClaimToThing>(expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_create_with_authentication_properties()
|
public void should_create_with_authentication_properties()
|
||||||
@ -486,7 +395,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod("Get")
|
.WithUpstreamHttpMethod("Get")
|
||||||
.WithUpstreamTemplatePattern("/api/products/.*/$")
|
|
||||||
.WithAuthenticationOptions(authenticationOptions)
|
.WithAuthenticationOptions(authenticationOptions)
|
||||||
.Build()
|
.Build()
|
||||||
};
|
};
|
||||||
@ -514,100 +422,12 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.And(x => x.GivenTheConfigIsValid())
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
|
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
||||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||||
.When(x => x.WhenICreateTheConfig())
|
.When(x => x.WhenICreateTheConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(expected))
|
.Then(x => x.ThenTheReRoutesAre(expected))
|
||||||
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
||||||
.BDDfy();
|
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_create_template_pattern_that_matches_more_than_one_placeholder()
|
|
||||||
{
|
|
||||||
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_more_than_one_placeholder_with_trailing_slash()
|
|
||||||
{
|
|
||||||
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();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,6 +462,9 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod);
|
result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod);
|
||||||
result.UpstreamPathTemplate.Value.ShouldBe(expected.UpstreamPathTemplate.Value);
|
result.UpstreamPathTemplate.Value.ShouldBe(expected.UpstreamPathTemplate.Value);
|
||||||
result.UpstreamTemplatePattern.ShouldBe(expected.UpstreamTemplatePattern);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,5 +522,32 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_qosProviderHouse
|
_qosProviderHouse
|
||||||
.Verify(x => x.Add(It.IsAny<string>(), _qosProvider.Object), Times.Once);
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user