mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 18:22:49 +08:00
Added tests for identity server reference tokens, general refactoring and come config validation
This commit is contained in:
parent
7289cd803b
commit
ce84ad4fc2
17
README.md
17
README.md
@ -31,6 +31,19 @@ Priorities
|
|||||||
- Rate Limiting
|
- Rate Limiting
|
||||||
- Then a big list of cool things...
|
- Then a big list of cool things...
|
||||||
|
|
||||||
## How to use
|
# How to use
|
||||||
|
|
||||||
TBC....
|
# Configuration
|
||||||
|
|
||||||
|
TBC really but example configuration for a route below.
|
||||||
|
|
||||||
|
ReRoutes:
|
||||||
|
- DownstreamTemplate: http://localhost:51876/
|
||||||
|
UpstreamTemplate: /
|
||||||
|
UpstreamHttpMethod: Post
|
||||||
|
AuthenticationOptions:
|
||||||
|
Provider: IdentityServer.AccessToken
|
||||||
|
ProviderRootUrl: http://localhost:51888
|
||||||
|
ScopeName: api
|
||||||
|
AdditionalScopes: []
|
||||||
|
ScopeSecret: secret
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
using AuthenticationOptions = Ocelot.Library.Infrastructure.Configuration.AuthenticationOptions;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Authentication
|
namespace Ocelot.Library.Infrastructure.Authentication
|
||||||
{
|
{
|
||||||
@ -9,17 +11,18 @@ namespace Ocelot.Library.Infrastructure.Authentication
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class AuthenticationHandlerCreator : IAuthenticationHandlerCreator
|
public class AuthenticationHandlerCreator : IAuthenticationHandlerCreator
|
||||||
{
|
{
|
||||||
public Response<RequestDelegate> CreateIdentityServerAuthenticationHandler(IApplicationBuilder app)
|
public Response<RequestDelegate> CreateIdentityServerAuthenticationHandler(IApplicationBuilder app, AuthenticationOptions authOptions)
|
||||||
{
|
{
|
||||||
var builder = app.New();
|
var builder = app.New();
|
||||||
|
|
||||||
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||||
{
|
{
|
||||||
//todo sort these options out
|
Authority = authOptions.ProviderRootUrl,
|
||||||
Authority = "http://localhost:51888",
|
ScopeName = authOptions.ScopeName,
|
||||||
ScopeName = "api",
|
RequireHttpsMetadata = authOptions.RequireHttps,
|
||||||
|
AdditionalScopes = authOptions.AdditionalScopes,
|
||||||
RequireHttpsMetadata = false
|
SupportedTokens = SupportedTokens.Both,
|
||||||
|
ScopeSecret = authOptions.ScopeSecret
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.UseMvc();
|
builder.UseMvc();
|
||||||
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Ocelot.Library.Infrastructure.Errors;
|
using Ocelot.Library.Infrastructure.Errors;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
using AuthenticationOptions = Ocelot.Library.Infrastructure.Configuration.AuthenticationOptions;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Authentication
|
namespace Ocelot.Library.Infrastructure.Authentication
|
||||||
{
|
{
|
||||||
@ -14,18 +15,18 @@ namespace Ocelot.Library.Infrastructure.Authentication
|
|||||||
_creator = creator;
|
_creator = creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response<AuthenticationHandler> Get(string provider, IApplicationBuilder app)
|
public Response<AuthenticationHandler> Get(IApplicationBuilder app, AuthenticationOptions authOptions)
|
||||||
{
|
{
|
||||||
var handler = _creator.CreateIdentityServerAuthenticationHandler(app);
|
var handler = _creator.CreateIdentityServerAuthenticationHandler(app, authOptions);
|
||||||
|
|
||||||
if (!handler.IsError)
|
if (!handler.IsError)
|
||||||
{
|
{
|
||||||
return new OkResponse<AuthenticationHandler>(new AuthenticationHandler(provider, handler.Data));
|
return new OkResponse<AuthenticationHandler>(new AuthenticationHandler(authOptions.Provider, handler.Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ErrorResponse<AuthenticationHandler>(new List<Error>
|
return new ErrorResponse<AuthenticationHandler>(new List<Error>
|
||||||
{
|
{
|
||||||
new UnableToCreateAuthenticationHandlerError($"Unable to create authentication handler for {provider}")
|
new UnableToCreateAuthenticationHandlerError($"Unable to create authentication handler for {authOptions.Provider}")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
using AuthenticationOptions = Ocelot.Library.Infrastructure.Configuration.AuthenticationOptions;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Authentication
|
namespace Ocelot.Library.Infrastructure.Authentication
|
||||||
{
|
{
|
||||||
public interface IAuthenticationHandlerCreator
|
public interface IAuthenticationHandlerCreator
|
||||||
{
|
{
|
||||||
Response<RequestDelegate> CreateIdentityServerAuthenticationHandler(IApplicationBuilder app);
|
Response<RequestDelegate> CreateIdentityServerAuthenticationHandler(IApplicationBuilder app, AuthenticationOptions authOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
using AuthenticationOptions = Ocelot.Library.Infrastructure.Configuration.AuthenticationOptions;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Authentication
|
namespace Ocelot.Library.Infrastructure.Authentication
|
||||||
{
|
{
|
||||||
public interface IAuthenticationHandlerFactory
|
public interface IAuthenticationHandlerFactory
|
||||||
{
|
{
|
||||||
Response<AuthenticationHandler> Get(string provider, IApplicationBuilder app);
|
Response<AuthenticationHandler> Get(IApplicationBuilder app, AuthenticationOptions authOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace Ocelot.Library.Infrastructure.Authentication
|
||||||
|
{
|
||||||
|
public enum SupportAuthenticationProviders
|
||||||
|
{
|
||||||
|
IdentityServer
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
namespace Ocelot.Library.Infrastructure.Builder
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Builder
|
||||||
{
|
{
|
||||||
using Configuration;
|
using Configuration;
|
||||||
|
|
||||||
@ -10,38 +12,84 @@
|
|||||||
private string _upstreamHttpMethod;
|
private string _upstreamHttpMethod;
|
||||||
private bool _isAuthenticated;
|
private bool _isAuthenticated;
|
||||||
private string _authenticationProvider;
|
private string _authenticationProvider;
|
||||||
|
private string _authenticationProviderUrl;
|
||||||
|
private string _scopeName;
|
||||||
|
private List<string> _additionalScopes;
|
||||||
|
private bool _requireHttps;
|
||||||
|
private string _scopeSecret;
|
||||||
|
|
||||||
public void WithDownstreamTemplate(string input)
|
public ReRouteBuilder()
|
||||||
|
{
|
||||||
|
_additionalScopes = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithDownstreamTemplate(string input)
|
||||||
{
|
{
|
||||||
_downstreamTemplate = input;
|
_downstreamTemplate = input;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WithUpstreamTemplate(string input)
|
public ReRouteBuilder WithUpstreamTemplate(string input)
|
||||||
{
|
{
|
||||||
_upstreamTemplate = input;
|
_upstreamTemplate = input;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WithUpstreamTemplatePattern(string input)
|
public ReRouteBuilder WithUpstreamTemplatePattern(string input)
|
||||||
{
|
{
|
||||||
_upstreamTemplatePattern = input;
|
_upstreamTemplatePattern = input;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
public void WithUpstreamHttpMethod(string input)
|
public ReRouteBuilder WithUpstreamHttpMethod(string input)
|
||||||
{
|
{
|
||||||
_upstreamHttpMethod = input;
|
_upstreamHttpMethod = input;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
public void WithIsAuthenticated(bool input)
|
public ReRouteBuilder WithIsAuthenticated(bool input)
|
||||||
{
|
{
|
||||||
_isAuthenticated = input;
|
_isAuthenticated = input;
|
||||||
|
return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
public void WithAuthenticationProvider(string input)
|
public ReRouteBuilder WithAuthenticationProvider(string input)
|
||||||
{
|
{
|
||||||
_authenticationProvider = input;
|
_authenticationProvider = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithAuthenticationProviderUrl(string input)
|
||||||
|
{
|
||||||
|
_authenticationProviderUrl = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithAuthenticationProviderScopeName(string input)
|
||||||
|
{
|
||||||
|
_scopeName = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithAuthenticationProviderAdditionalScopes(List<string> input)
|
||||||
|
{
|
||||||
|
_additionalScopes = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithRequireHttps(bool input)
|
||||||
|
{
|
||||||
|
_requireHttps = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithScopeSecret(string input)
|
||||||
|
{
|
||||||
|
_scopeSecret = input;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReRoute Build()
|
public ReRoute Build()
|
||||||
{
|
{
|
||||||
return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, _isAuthenticated, _authenticationProvider);
|
return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, _requireHttps, _additionalScopes, _scopeSecret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration
|
||||||
|
{
|
||||||
|
public class AuthenticationOptions
|
||||||
|
{
|
||||||
|
public AuthenticationOptions(string provider, string providerRootUrl, string scopeName, bool requireHttps, List<string> additionalScopes, string scopeSecret)
|
||||||
|
{
|
||||||
|
Provider = provider;
|
||||||
|
ProviderRootUrl = providerRootUrl;
|
||||||
|
ScopeName = scopeName;
|
||||||
|
RequireHttps = requireHttps;
|
||||||
|
AdditionalScopes = additionalScopes;
|
||||||
|
ScopeSecret = scopeSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Provider { get; private set; }
|
||||||
|
public string ProviderRootUrl { get; private set; }
|
||||||
|
public string ScopeName { get; private set; }
|
||||||
|
public string ScopeSecret { get; private set; }
|
||||||
|
public bool RequireHttps { get; private set; }
|
||||||
|
public List<string> AdditionalScopes { get; private set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -7,22 +7,40 @@ namespace Ocelot.Library.Infrastructure.Configuration
|
|||||||
public class OcelotConfiguration : IOcelotConfiguration
|
public class OcelotConfiguration : IOcelotConfiguration
|
||||||
{
|
{
|
||||||
private readonly IOptions<YamlConfiguration> _options;
|
private readonly IOptions<YamlConfiguration> _options;
|
||||||
|
private readonly IConfigurationValidator _configurationValidator;
|
||||||
private readonly List<ReRoute> _reRoutes;
|
private readonly List<ReRoute> _reRoutes;
|
||||||
private const string RegExMatchEverything = ".*";
|
private const string RegExMatchEverything = ".*";
|
||||||
private const string RegExMatchEndString = "$";
|
private const string RegExMatchEndString = "$";
|
||||||
|
|
||||||
public OcelotConfiguration(IOptions<YamlConfiguration> options)
|
public OcelotConfiguration(IOptions<YamlConfiguration> options, IConfigurationValidator configurationValidator)
|
||||||
{
|
{
|
||||||
_options = options;
|
_options = options;
|
||||||
|
_configurationValidator = configurationValidator;
|
||||||
_reRoutes = new List<ReRoute>();
|
_reRoutes = new List<ReRoute>();
|
||||||
SetReRoutes();
|
SetUpConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetReRoutes()
|
/// <summary>
|
||||||
|
/// This method is meant to be tempoary to convert a yaml config to an ocelot config...probably wont keep this but we will see
|
||||||
|
/// will need a refactor at some point as its crap
|
||||||
|
/// </summary>
|
||||||
|
private void SetUpConfiguration()
|
||||||
{
|
{
|
||||||
foreach(var reRoute in _options.Value.ReRoutes)
|
var response = _configurationValidator.IsValid(_options.Value);
|
||||||
|
|
||||||
|
if (!response.IsError && !response.Data.IsError)
|
||||||
|
{
|
||||||
|
foreach (var reRoute in _options.Value.ReRoutes)
|
||||||
|
{
|
||||||
|
SetUpReRoute(reRoute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetUpReRoute(YamlReRoute reRoute)
|
||||||
{
|
{
|
||||||
var upstreamTemplate = reRoute.UpstreamTemplate;
|
var upstreamTemplate = reRoute.UpstreamTemplate;
|
||||||
|
|
||||||
var placeholders = new List<string>();
|
var placeholders = new List<string>();
|
||||||
|
|
||||||
for (int i = 0; i < upstreamTemplate.Length; i++)
|
for (int i = 0; i < upstreamTemplate.Length; i++)
|
||||||
@ -43,13 +61,27 @@ namespace Ocelot.Library.Infrastructure.Configuration
|
|||||||
|
|
||||||
upstreamTemplate = $"{upstreamTemplate}{RegExMatchEndString}";
|
upstreamTemplate = $"{upstreamTemplate}{RegExMatchEndString}";
|
||||||
|
|
||||||
var isAuthenticated = !string.IsNullOrEmpty(reRoute.Authentication);
|
var isAuthenticated = !string.IsNullOrEmpty(reRoute.AuthenticationOptions?.Provider);
|
||||||
|
|
||||||
_reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, reRoute.Authentication));
|
if (isAuthenticated)
|
||||||
|
{
|
||||||
|
var authOptionsForRoute = new AuthenticationOptions(reRoute.AuthenticationOptions.Provider,
|
||||||
|
reRoute.AuthenticationOptions.ProviderRootUrl, reRoute.AuthenticationOptions.ScopeName,
|
||||||
|
reRoute.AuthenticationOptions.RequireHttps, reRoute.AuthenticationOptions.AdditionalScopes,
|
||||||
|
reRoute.AuthenticationOptions.ScopeSecret);
|
||||||
|
|
||||||
|
_reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate,
|
||||||
|
reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, authOptionsForRoute
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod,
|
||||||
|
upstreamTemplate, isAuthenticated, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPlaceHolder(string upstreamTemplate, int i)
|
private bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||||
{
|
{
|
||||||
return upstreamTemplate[i] == '{';
|
return upstreamTemplate[i] == '{';
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
{
|
{
|
||||||
public class ReRoute
|
public class ReRoute
|
||||||
{
|
{
|
||||||
public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated, string authenticationProvider)
|
public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated, AuthenticationOptions authenticationOptions)
|
||||||
{
|
{
|
||||||
DownstreamTemplate = downstreamTemplate;
|
DownstreamTemplate = downstreamTemplate;
|
||||||
UpstreamTemplate = upstreamTemplate;
|
UpstreamTemplate = upstreamTemplate;
|
||||||
UpstreamHttpMethod = upstreamHttpMethod;
|
UpstreamHttpMethod = upstreamHttpMethod;
|
||||||
UpstreamTemplatePattern = upstreamTemplatePattern;
|
UpstreamTemplatePattern = upstreamTemplatePattern;
|
||||||
IsAuthenticated = isAuthenticated;
|
IsAuthenticated = isAuthenticated;
|
||||||
AuthenticationProvider = authenticationProvider;
|
AuthenticationOptions = authenticationOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DownstreamTemplate { get; private set; }
|
public string DownstreamTemplate { get; private set; }
|
||||||
@ -17,6 +17,6 @@
|
|||||||
public string UpstreamTemplatePattern { get; private set; }
|
public string UpstreamTemplatePattern { get; private set; }
|
||||||
public string UpstreamHttpMethod { get; private set; }
|
public string UpstreamHttpMethod { get; private set; }
|
||||||
public bool IsAuthenticated { get; private set; }
|
public bool IsAuthenticated { get; private set; }
|
||||||
public string AuthenticationProvider { get; private set; }
|
public AuthenticationOptions AuthenticationOptions { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Ocelot.Library.Infrastructure.Authentication;
|
||||||
using Ocelot.Library.Infrastructure.Errors;
|
using Ocelot.Library.Infrastructure.Errors;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
@ -8,6 +10,59 @@ namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
|||||||
public class ConfigurationValidator : IConfigurationValidator
|
public class ConfigurationValidator : IConfigurationValidator
|
||||||
{
|
{
|
||||||
public Response<ConfigurationValidationResult> IsValid(YamlConfiguration configuration)
|
public Response<ConfigurationValidationResult> IsValid(YamlConfiguration configuration)
|
||||||
|
{
|
||||||
|
var result = CheckForDupliateReRoutes(configuration);
|
||||||
|
|
||||||
|
if (result.IsError)
|
||||||
|
{
|
||||||
|
return new OkResponse<ConfigurationValidationResult>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = CheckForUnsupportedAuthenticationProviders(configuration);
|
||||||
|
|
||||||
|
if (result.IsError)
|
||||||
|
{
|
||||||
|
return new OkResponse<ConfigurationValidationResult>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OkResponse<ConfigurationValidationResult>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigurationValidationResult CheckForUnsupportedAuthenticationProviders(YamlConfiguration configuration)
|
||||||
|
{
|
||||||
|
var errors = new List<Error>();
|
||||||
|
|
||||||
|
foreach (var yamlReRoute in configuration.ReRoutes)
|
||||||
|
{
|
||||||
|
var isAuthenticated = !string.IsNullOrEmpty(yamlReRoute.AuthenticationOptions?.Provider);
|
||||||
|
|
||||||
|
if (!isAuthenticated)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSupportedAuthenticationProvider(yamlReRoute.AuthenticationOptions?.Provider))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = new UnsupportedAuthenticationProviderError($"{yamlReRoute.AuthenticationOptions?.Provider} is unsupported authentication provider, upstream template is {yamlReRoute.UpstreamTemplate}, upstream method is {yamlReRoute.UpstreamHttpMethod}");
|
||||||
|
errors.Add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Count > 0
|
||||||
|
? new ConfigurationValidationResult(true, errors)
|
||||||
|
: new ConfigurationValidationResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsSupportedAuthenticationProvider(string provider)
|
||||||
|
{
|
||||||
|
SupportAuthenticationProviders supportedProvider;
|
||||||
|
|
||||||
|
return Enum.TryParse(provider, true, out supportedProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigurationValidationResult CheckForDupliateReRoutes(YamlConfiguration configuration)
|
||||||
{
|
{
|
||||||
var duplicateUpstreamTemplates = configuration.ReRoutes
|
var duplicateUpstreamTemplates = configuration.ReRoutes
|
||||||
.Select(r => r.DownstreamTemplate)
|
.Select(r => r.DownstreamTemplate)
|
||||||
@ -18,19 +73,15 @@ namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
|||||||
|
|
||||||
if (duplicateUpstreamTemplates.Count <= 0)
|
if (duplicateUpstreamTemplates.Count <= 0)
|
||||||
{
|
{
|
||||||
return new OkResponse<ConfigurationValidationResult>(new ConfigurationValidationResult(false));
|
return new ConfigurationValidationResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var errors = new List<Error>();
|
var errors = duplicateUpstreamTemplates
|
||||||
|
.Select(duplicateUpstreamTemplate => new DownstreamTemplateAlreadyUsedError(string.Format("Duplicate DownstreamTemplate: {0}", duplicateUpstreamTemplate)))
|
||||||
|
.Cast<Error>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var duplicateUpstreamTemplate in duplicateUpstreamTemplates)
|
return new ConfigurationValidationResult(true, errors);
|
||||||
{
|
|
||||||
var error = new DownstreamTemplateAlreadyUsedError(string.Format("Duplicate DownstreamTemplate: {0}",
|
|
||||||
duplicateUpstreamTemplate));
|
|
||||||
errors.Add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new OkResponse<ConfigurationValidationResult>(new ConfigurationValidationResult(true, errors));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
using Ocelot.Library.Infrastructure.Errors;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
|
{
|
||||||
|
public class UnsupportedAuthenticationProviderError : Error
|
||||||
|
{
|
||||||
|
public UnsupportedAuthenticationProviderError(string message)
|
||||||
|
: base(message, OcelotErrorCode.UnsupportedAuthenticationProviderError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
|
{
|
||||||
|
public class YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
public string Provider { get; set; }
|
||||||
|
public string ProviderRootUrl { get; set; }
|
||||||
|
public string ScopeName { get; set; }
|
||||||
|
public bool RequireHttps { get; set; }
|
||||||
|
public List<string> AdditionalScopes { get; set; }
|
||||||
|
public string ScopeSecret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,6 @@
|
|||||||
public string DownstreamTemplate { get; set; }
|
public string DownstreamTemplate { get; set; }
|
||||||
public string UpstreamTemplate { get; set; }
|
public string UpstreamTemplate { get; set; }
|
||||||
public string UpstreamHttpMethod { get; set; }
|
public string UpstreamHttpMethod { get; set; }
|
||||||
public string Authentication { get; set; }
|
public YamlAuthenticationOptions AuthenticationOptions { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@
|
|||||||
CannotAddDataError,
|
CannotAddDataError,
|
||||||
CannotFindDataError,
|
CannotFindDataError,
|
||||||
UnableToCompleteRequestError,
|
UnableToCompleteRequestError,
|
||||||
UnableToCreateAuthenticationHandlerError
|
UnableToCreateAuthenticationHandlerError,
|
||||||
|
UnsupportedAuthenticationProviderError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,18 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Library.Infrastructure.Authentication;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.Errors;
|
using Ocelot.Library.Infrastructure.Errors;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Ocelot.Library.Infrastructure.Authentication;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Middleware
|
namespace Ocelot.Library.Infrastructure.Middleware
|
||||||
{
|
{
|
||||||
public class AuthenticationMiddleware : OcelotMiddleware
|
public class AuthenticationMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private RequestDelegate _authenticationNext;
|
|
||||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
private readonly IApplicationBuilder _app;
|
private readonly IApplicationBuilder _app;
|
||||||
private readonly IAuthenticationHandlerFactory _authHandlerFactory;
|
private readonly IAuthenticationHandlerFactory _authHandlerFactory;
|
||||||
@ -46,7 +39,7 @@ namespace Ocelot.Library.Infrastructure.Middleware
|
|||||||
|
|
||||||
if (IsAuthenticatedRoute(downstreamRoute.Data.ReRoute))
|
if (IsAuthenticatedRoute(downstreamRoute.Data.ReRoute))
|
||||||
{
|
{
|
||||||
var authenticationNext = _authHandlerFactory.Get(downstreamRoute.Data.ReRoute.AuthenticationProvider, _app);
|
var authenticationNext = _authHandlerFactory.Get(_app, downstreamRoute.Data.ReRoute.AuthenticationOptions);
|
||||||
|
|
||||||
if (!authenticationNext.IsError)
|
if (!authenticationNext.IsError)
|
||||||
{
|
{
|
||||||
|
@ -43,11 +43,13 @@ namespace Ocelot
|
|||||||
services.AddOptions();
|
services.AddOptions();
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
services.AddMvcCore().AddAuthorization().AddJsonFormatters();
|
services.AddMvcCore().AddAuthorization().AddJsonFormatters();
|
||||||
|
services.AddAuthentication();
|
||||||
|
services.AddLogging();
|
||||||
|
|
||||||
services.Configure<YamlConfiguration>(Configuration);
|
services.Configure<YamlConfiguration>(Configuration);
|
||||||
services.AddAuthentication();
|
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
|
services.AddSingleton<IConfigurationValidator, ConfigurationValidator>();
|
||||||
services.AddSingleton<IOcelotConfiguration, OcelotConfiguration>();
|
services.AddSingleton<IOcelotConfiguration, OcelotConfiguration>();
|
||||||
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
||||||
services.AddSingleton<ITemplateVariableNameAndValueFinder, TemplateVariableNameAndValueFinder>();
|
services.AddSingleton<ITemplateVariableNameAndValueFinder, TemplateVariableNameAndValueFinder>();
|
||||||
|
@ -43,7 +43,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_401_using_identity_server_access_token()
|
public void should_return_401_using_identity_server_access_token()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888"))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
|
||||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
||||||
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||||
{
|
{
|
||||||
@ -54,7 +54,48 @@ namespace Ocelot.AcceptanceTests
|
|||||||
DownstreamTemplate = "http://localhost:51876/",
|
DownstreamTemplate = "http://localhost:51876/",
|
||||||
UpstreamTemplate = "/",
|
UpstreamTemplate = "/",
|
||||||
UpstreamHttpMethod = "Post",
|
UpstreamHttpMethod = "Post",
|
||||||
Authentication = "JwtBearerAuthentication"
|
AuthenticationOptions = new YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
AdditionalScopes = new List<string>(),
|
||||||
|
Provider = "IdentityServer",
|
||||||
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
|
RequireHttps = false,
|
||||||
|
ScopeName = "api",
|
||||||
|
ScopeSecret = "secret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.And(x => x.GivenTheApiGatewayIsRunning())
|
||||||
|
.And(x => x.GivenThePostHasContent("postContent"))
|
||||||
|
.When(x => x.WhenIPostUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_401_using_identity_server_reference_token()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Reference))
|
||||||
|
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
||||||
|
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
DownstreamTemplate = "http://localhost:51876/",
|
||||||
|
UpstreamTemplate = "/",
|
||||||
|
UpstreamHttpMethod = "Post",
|
||||||
|
AuthenticationOptions = new YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
AdditionalScopes = new List<string>(),
|
||||||
|
Provider = "IdentityServer",
|
||||||
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
|
RequireHttps = false,
|
||||||
|
ScopeName = "api",
|
||||||
|
ScopeSecret = "secret"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@ -68,7 +109,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_201_using_identity_server_access_token()
|
public void should_return_201_using_identity_server_access_token()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888"))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
|
||||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
||||||
.And(x => x.GivenIHaveAToken("http://localhost:51888"))
|
.And(x => x.GivenIHaveAToken("http://localhost:51888"))
|
||||||
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||||
@ -80,7 +121,50 @@ namespace Ocelot.AcceptanceTests
|
|||||||
DownstreamTemplate = "http://localhost:51876/",
|
DownstreamTemplate = "http://localhost:51876/",
|
||||||
UpstreamTemplate = "/",
|
UpstreamTemplate = "/",
|
||||||
UpstreamHttpMethod = "Post",
|
UpstreamHttpMethod = "Post",
|
||||||
Authentication = "JwtBearerAuthentication"
|
AuthenticationOptions = new YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
AdditionalScopes = new List<string>(),
|
||||||
|
Provider = "IdentityServer",
|
||||||
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
|
RequireHttps = false,
|
||||||
|
ScopeName = "api",
|
||||||
|
ScopeSecret = "secret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.And(x => x.GivenTheApiGatewayIsRunning())
|
||||||
|
.And(x => x.GivenIHaveAddedATokenToMyRequest())
|
||||||
|
.And(x => x.GivenThePostHasContent("postContent"))
|
||||||
|
.When(x => x.WhenIPostUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.Created))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_201_using_identity_server_reference_token()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Reference))
|
||||||
|
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
||||||
|
.And(x => x.GivenIHaveAToken("http://localhost:51888"))
|
||||||
|
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
DownstreamTemplate = "http://localhost:51876/",
|
||||||
|
UpstreamTemplate = "/",
|
||||||
|
UpstreamHttpMethod = "Post",
|
||||||
|
AuthenticationOptions = new YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
AdditionalScopes = new List<string>(),
|
||||||
|
Provider = "IdentityServer",
|
||||||
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
|
RequireHttps = false,
|
||||||
|
ScopeName = "api",
|
||||||
|
ScopeSecret = "secret"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@ -144,7 +228,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_ocelotBbuilder.Start();
|
_ocelotBbuilder.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsAnIdentityServerOn(string url)
|
private void GivenThereIsAnIdentityServerOn(string url, string scopeName, AccessTokenType tokenType)
|
||||||
{
|
{
|
||||||
_identityServerBuilder = new WebHostBuilder()
|
_identityServerBuilder = new WebHostBuilder()
|
||||||
.UseUrls(url)
|
.UseUrls(url)
|
||||||
@ -154,13 +238,21 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.UseUrls(url)
|
.UseUrls(url)
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
services.AddLogging();
|
||||||
services.AddDeveloperIdentityServer()
|
services.AddDeveloperIdentityServer()
|
||||||
.AddInMemoryScopes(new List<Scope> { new Scope
|
.AddInMemoryScopes(new List<Scope> { new Scope
|
||||||
{
|
{
|
||||||
Name = "api",
|
Name = scopeName,
|
||||||
Description = "My API",
|
Description = "My API",
|
||||||
Enabled = true
|
Enabled = true,
|
||||||
|
AllowUnrestrictedIntrospection = true,
|
||||||
|
ScopeSecrets = new List<Secret>()
|
||||||
|
{
|
||||||
|
new Secret
|
||||||
|
{
|
||||||
|
Value = "secret".Sha256()
|
||||||
|
}
|
||||||
|
}
|
||||||
}})
|
}})
|
||||||
.AddInMemoryClients(new List<Client> {
|
.AddInMemoryClients(new List<Client> {
|
||||||
new Client
|
new Client
|
||||||
@ -168,8 +260,8 @@ namespace Ocelot.AcceptanceTests
|
|||||||
ClientId = "client",
|
ClientId = "client",
|
||||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||||
ClientSecrets = new List<Secret> { new Secret("secret".Sha256()) },
|
ClientSecrets = new List<Secret> { new Secret("secret".Sha256()) },
|
||||||
AllowedScopes = new List<string> { "api" },
|
AllowedScopes = new List<string> { scopeName },
|
||||||
AccessTokenType = AccessTokenType.Jwt,
|
AccessTokenType = tokenType,
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
RequireClientSecret = false
|
RequireClientSecret = false
|
||||||
} })
|
} })
|
||||||
@ -248,6 +340,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_identityServerBuilder?.Dispose();
|
_identityServerBuilder?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once ClassNeverInstantiated.Local
|
||||||
class BearerToken
|
class BearerToken
|
||||||
{
|
{
|
||||||
[JsonProperty("access_token")]
|
[JsonProperty("access_token")]
|
||||||
|
@ -17,8 +17,7 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
private readonly IAuthenticationHandlerFactory _authenticationHandlerFactory;
|
private readonly IAuthenticationHandlerFactory _authenticationHandlerFactory;
|
||||||
private readonly Mock<IApplicationBuilder> _app;
|
private readonly Mock<IApplicationBuilder> _app;
|
||||||
private readonly Mock<IAuthenticationHandlerCreator> _creator;
|
private readonly Mock<IAuthenticationHandlerCreator> _creator;
|
||||||
|
private Library.Infrastructure.Configuration.AuthenticationOptions _authenticationOptions;
|
||||||
private string _provider;
|
|
||||||
private Response<AuthenticationHandler> _result;
|
private Response<AuthenticationHandler> _result;
|
||||||
|
|
||||||
public AuthenticationHandlerFactoryTests()
|
public AuthenticationHandlerFactoryTests()
|
||||||
@ -31,27 +30,32 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_identity_server_access_token_handler()
|
public void should_return_identity_server_access_token_handler()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheProviderIs("IdentityServer.AccessToken"))
|
this.Given(x => x.GivenTheAuthenticationOptionsAre(new Library.Infrastructure.Configuration.AuthenticationOptions("IdentityServer", "","",false, new List<string>(), "")))
|
||||||
.And(x => x.GivenTheCreatorReturns())
|
.And(x => x.GivenTheCreatorReturns())
|
||||||
.When(x => x.WhenIGetFromTheFactory())
|
.When(x => x.WhenIGetFromTheFactory())
|
||||||
.Then(x => x.ThenTheHandlerIsReturned("IdentityServer.AccessToken"))
|
.Then(x => x.ThenTheHandlerIsReturned("IdentityServer"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_error_if_cannot_create_handler()
|
public void should_return_error_if_cannot_create_handler()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheProviderIs("IdentityServer.AccessToken"))
|
this.Given(x => x.GivenTheAuthenticationOptionsAre(new Library.Infrastructure.Configuration.AuthenticationOptions("IdentityServer", "", "", false, new List<string>(), "")))
|
||||||
.And(x => x.GivenTheCreatorReturnsAnError())
|
.And(x => x.GivenTheCreatorReturnsAnError())
|
||||||
.When(x => x.WhenIGetFromTheFactory())
|
.When(x => x.WhenIGetFromTheFactory())
|
||||||
.Then(x => x.ThenAnErrorResponseIsReturned())
|
.Then(x => x.ThenAnErrorResponseIsReturned())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenTheAuthenticationOptionsAre(Library.Infrastructure.Configuration.AuthenticationOptions authenticationOptions)
|
||||||
|
{
|
||||||
|
_authenticationOptions = authenticationOptions;
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheCreatorReturnsAnError()
|
private void GivenTheCreatorReturnsAnError()
|
||||||
{
|
{
|
||||||
_creator
|
_creator
|
||||||
.Setup(x => x.CreateIdentityServerAuthenticationHandler(It.IsAny<IApplicationBuilder>()))
|
.Setup(x => x.CreateIdentityServerAuthenticationHandler(It.IsAny<IApplicationBuilder>(), It.IsAny<Library.Infrastructure.Configuration.AuthenticationOptions>()))
|
||||||
.Returns(new ErrorResponse<RequestDelegate>(new List<Error>
|
.Returns(new ErrorResponse<RequestDelegate>(new List<Error>
|
||||||
{
|
{
|
||||||
new UnableToCreateAuthenticationHandlerError($"Unable to create authentication handler for xxx")
|
new UnableToCreateAuthenticationHandlerError($"Unable to create authentication handler for xxx")
|
||||||
@ -61,18 +65,13 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
private void GivenTheCreatorReturns()
|
private void GivenTheCreatorReturns()
|
||||||
{
|
{
|
||||||
_creator
|
_creator
|
||||||
.Setup(x => x.CreateIdentityServerAuthenticationHandler(It.IsAny<IApplicationBuilder>()))
|
.Setup(x => x.CreateIdentityServerAuthenticationHandler(It.IsAny<IApplicationBuilder>(), It.IsAny<Library.Infrastructure.Configuration.AuthenticationOptions>()))
|
||||||
.Returns(new OkResponse<RequestDelegate>(x => Task.CompletedTask));
|
.Returns(new OkResponse<RequestDelegate>(x => Task.CompletedTask));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheProviderIs(string provider)
|
|
||||||
{
|
|
||||||
_provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenIGetFromTheFactory()
|
private void WhenIGetFromTheFactory()
|
||||||
{
|
{
|
||||||
_result = _authenticationHandlerFactory.Get(_provider, _app.Object);
|
_result = _authenticationHandlerFactory.Get(_app.Object, _authenticationOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheHandlerIsReturned(string expected)
|
private void ThenTheHandlerIsReturned(string expected)
|
||||||
|
@ -37,6 +37,53 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void configuration_is_valid_with_valid_authentication_provider()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenAConfiguration(new YamlConfiguration()
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
DownstreamTemplate = "http://www.bbc.co.uk",
|
||||||
|
UpstreamTemplate = "http://asdf.com",
|
||||||
|
AuthenticationOptions = new YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
Provider = "IdentityServer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.When(x => x.WhenIValidateTheConfiguration())
|
||||||
|
.Then(x => x.ThenTheResultIsValid())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void configuration_is_invalid_with_invalid_authentication_provider()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenAConfiguration(new YamlConfiguration()
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
DownstreamTemplate = "http://www.bbc.co.uk",
|
||||||
|
UpstreamTemplate = "http://asdf.com",
|
||||||
|
AuthenticationOptions = new YamlAuthenticationOptions
|
||||||
|
{
|
||||||
|
Provider = "BootyBootyBottyRockinEverywhere"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.When(x => x.WhenIValidateTheConfiguration())
|
||||||
|
.Then(x => x.ThenTheResultIsNotValid())
|
||||||
|
.And(x => x.ThenTheErrorIs<UnsupportedAuthenticationProviderError>())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void configuration_is_not_valid_with_duplicate_reroutes()
|
public void configuration_is_not_valid_with_duplicate_reroutes()
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using Ocelot.Library.Infrastructure.Builder;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -12,11 +14,13 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
public class OcelotConfigurationTests
|
public class OcelotConfigurationTests
|
||||||
{
|
{
|
||||||
private readonly Mock<IOptions<YamlConfiguration>> _yamlConfig;
|
private readonly Mock<IOptions<YamlConfiguration>> _yamlConfig;
|
||||||
|
private readonly Mock<IConfigurationValidator> _validator;
|
||||||
private OcelotConfiguration _config;
|
private OcelotConfiguration _config;
|
||||||
private YamlConfiguration _yamlConfiguration;
|
private YamlConfiguration _yamlConfiguration;
|
||||||
|
|
||||||
public OcelotConfigurationTests()
|
public OcelotConfigurationTests()
|
||||||
{
|
{
|
||||||
|
_validator = new Mock<IConfigurationValidator>();
|
||||||
_yamlConfig = new Mock<IOptions<YamlConfiguration>>();
|
_yamlConfig = new Mock<IOptions<YamlConfiguration>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,10 +39,16 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.And(x => x.GivenTheYamlConfigIsValid())
|
||||||
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("/products/{productId}","/api/products/{productId}", "Get", "/api/products/.*$", false, "")
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("/products/{productId}")
|
||||||
|
.WithUpstreamTemplate("/api/products/{productId}")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("/api/products/.*$")
|
||||||
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
@ -58,10 +68,16 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.And(x => x.GivenTheYamlConfigIsValid())
|
||||||
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("/products/{productId}","/api/products/{productId}/variants/{variantId}", "Get", "/api/products/.*/variants/.*$", false, "")
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("/products/{productId}")
|
||||||
|
.WithUpstreamTemplate("/api/products/{productId}/variants/{variantId}")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("/api/products/.*/variants/.*$")
|
||||||
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
@ -81,10 +97,16 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.And(x => x.GivenTheYamlConfigIsValid())
|
||||||
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("/products/{productId}","/api/products/{productId}/variants/{variantId}/", "Get", "/api/products/.*/variants/.*/$", false, "")
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("/products/{productId}")
|
||||||
|
.WithUpstreamTemplate("/api/products/{productId}/variants/{variantId}/")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("/api/products/.*/variants/.*/$")
|
||||||
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
@ -104,14 +126,27 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.And(x => x.GivenTheYamlConfigIsValid())
|
||||||
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("/api/products/","/", "Get", "/$", false, "")
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("/api/products/")
|
||||||
|
.WithUpstreamTemplate("/")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("/$")
|
||||||
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenTheYamlConfigIsValid()
|
||||||
|
{
|
||||||
|
_validator
|
||||||
|
.Setup(x => x.IsValid(It.IsAny<YamlConfiguration>()))
|
||||||
|
.Returns(new OkResponse<ConfigurationValidationResult>(new ConfigurationValidationResult(false)));
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheYamlConfigIs(YamlConfiguration yamlConfiguration)
|
private void GivenTheYamlConfigIs(YamlConfiguration yamlConfiguration)
|
||||||
{
|
{
|
||||||
_yamlConfiguration = yamlConfiguration;
|
_yamlConfiguration = yamlConfiguration;
|
||||||
@ -122,7 +157,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
|
|
||||||
private void WhenIInstanciateTheOcelotConfig()
|
private void WhenIInstanciateTheOcelotConfig()
|
||||||
{
|
{
|
||||||
_config = new OcelotConfiguration(_yamlConfig.Object);
|
_config = new OcelotConfiguration(_yamlConfig.Object, _validator.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheReRoutesAre(List<ReRoute> expectedReRoutes)
|
private void ThenTheReRoutesAre(List<ReRoute> expectedReRoutes)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using Ocelot.Library.Infrastructure.Builder;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
@ -34,17 +35,29 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
public void should_return_route()
|
public void should_return_route()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
||||||
.And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
|
.And(
|
||||||
|
x =>
|
||||||
|
x.GivenTheTemplateVariableAndNameFinderReturns(
|
||||||
|
new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
|
||||||
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("someDownstreamPath","someUpstreamPath", "Get", "someUpstreamPath", false, "")
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("someDownstreamPath")
|
||||||
|
.WithUpstreamTemplate("someUpstreamPath")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("someUpstreamPath")
|
||||||
|
.Build()
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
||||||
.When(x => x.WhenICallTheFinder())
|
.When(x => x.WhenICallTheFinder())
|
||||||
.Then(
|
.Then(
|
||||||
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("someDownstreamPath","","","",false, ""))))
|
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<TemplateVariableNameAndValue>(),
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("someDownstreamPath")
|
||||||
|
.Build()
|
||||||
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
@ -53,18 +66,35 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
public void should_return_correct_route_for_http_verb()
|
public void should_return_correct_route_for_http_verb()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
||||||
.And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
|
.And(
|
||||||
|
x =>
|
||||||
|
x.GivenTheTemplateVariableAndNameFinderReturns(
|
||||||
|
new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
|
||||||
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("someDownstreamPath", "someUpstreamPath", "Get", string.Empty, false, ""),
|
new ReRouteBuilder()
|
||||||
new ReRoute("someDownstreamPathForAPost", "someUpstreamPath", "Post", string.Empty, false, "")
|
.WithDownstreamTemplate("someDownstreamPath")
|
||||||
|
.WithUpstreamTemplate("someUpstreamPath")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("")
|
||||||
|
.Build(),
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("someDownstreamPathForAPost")
|
||||||
|
.WithUpstreamTemplate("someUpstreamPath")
|
||||||
|
.WithUpstreamHttpMethod("Post")
|
||||||
|
.WithUpstreamTemplatePattern("")
|
||||||
|
.Build()
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
|
||||||
.When(x => x.WhenICallTheFinder())
|
.When(x => x.WhenICallTheFinder())
|
||||||
.Then(
|
.Then(
|
||||||
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("someDownstreamPathForAPost", "","","",false, ""))))
|
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<TemplateVariableNameAndValue>(),
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("someDownstreamPathForAPost")
|
||||||
|
.Build()
|
||||||
|
)))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +104,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath"))
|
||||||
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute("somPath", "somePath", "Get", "somePath", false, "")
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamTemplate("somPath")
|
||||||
|
.WithUpstreamTemplate("somePath")
|
||||||
|
.WithUpstreamHttpMethod("Get")
|
||||||
|
.WithUpstreamTemplatePattern("somePath")
|
||||||
|
.Build(),
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false))))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false))))
|
||||||
|
@ -7,6 +7,7 @@ using Microsoft.AspNetCore.TestHost;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Library.Infrastructure.Authentication;
|
using Ocelot.Library.Infrastructure.Authentication;
|
||||||
|
using Ocelot.Library.Infrastructure.Builder;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.Middleware;
|
using Ocelot.Library.Infrastructure.Middleware;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
@ -57,7 +58,7 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void happy_path()
|
public void happy_path()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("","","","",false, ""))))
|
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().Build())))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenNoExceptionsAreThrown())
|
.Then(x => x.ThenNoExceptionsAreThrown())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
using Ocelot.Library.Infrastructure.Middleware;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Library.Infrastructure.Builder;
|
||||||
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
|
using Ocelot.Library.Infrastructure.Middleware;
|
||||||
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
using Ocelot.Library.Infrastructure.UrlMatcher;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Middleware
|
namespace Ocelot.UnitTests.Middleware
|
||||||
{
|
{
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Library.Infrastructure.Configuration;
|
|
||||||
using Library.Infrastructure.DownstreamRouteFinder;
|
|
||||||
using Library.Infrastructure.Repository;
|
|
||||||
using Library.Infrastructure.Responses;
|
|
||||||
using Library.Infrastructure.UrlMatcher;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
|
||||||
using TestStack.BDDfy;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
public class DownstreamRouteFinderMiddlewareTests : IDisposable
|
public class DownstreamRouteFinderMiddlewareTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Mock<IDownstreamRouteFinder> _downstreamRouteFinder;
|
private readonly Mock<IDownstreamRouteFinder> _downstreamRouteFinder;
|
||||||
@ -57,7 +56,7 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void happy_path()
|
public void happy_path()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("any old string", "", "", "",false, ""))))
|
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
|
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Ocelot.Library.Infrastructure.Middleware;
|
using Ocelot.Library.Infrastructure.Builder;
|
||||||
|
using Ocelot.Library.Infrastructure.Middleware;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Middleware
|
namespace Ocelot.UnitTests.Middleware
|
||||||
{
|
{
|
||||||
@ -59,7 +60,7 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void happy_path()
|
public void happy_path()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("any old string", "", "", "", false, ""))))
|
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
|
||||||
.And(x => x.TheUrlReplacerReturns("any old string"))
|
.And(x => x.TheUrlReplacerReturns("any old string"))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
|
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Ocelot.Library.Infrastructure.Builder;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Ocelot.Library.Infrastructure.UrlMatcher;
|
using Ocelot.Library.Infrastructure.UrlMatcher;
|
||||||
@ -25,7 +26,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_replace_no_template_variables()
|
public void can_replace_no_template_variables()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned(""))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned(""))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -34,7 +35,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_replace_no_template_variables_with_slash()
|
public void can_replace_no_template_variables_with_slash()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("/", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("/").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("/"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("/"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -43,7 +44,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_replace_url_no_slash()
|
public void can_replace_url_no_slash()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("api", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -52,7 +53,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_replace_url_one_slash()
|
public void can_replace_url_one_slash()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("api/", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -61,7 +62,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_replace_url_multiple_slash()
|
public void can_replace_url_multiple_slash()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRoute("api/product/products/", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/product/products/").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/product/products/"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/product/products/"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -75,7 +76,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
new TemplateVariableNameAndValue("{productId}", "1")
|
new TemplateVariableNameAndValue("{productId}", "1")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRoute("productservice/products/{productId}/", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -89,7 +90,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
new TemplateVariableNameAndValue("{productId}", "1")
|
new TemplateVariableNameAndValue("{productId}", "1")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRoute("productservice/products/{productId}/variants", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/variants").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -104,7 +105,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
new TemplateVariableNameAndValue("{variantId}", "12")
|
new TemplateVariableNameAndValue("{variantId}", "12")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRoute("productservice/products/{productId}/variants/{variantId}", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/variants/{variantId}").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants/12"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants/12"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -120,7 +121,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
new TemplateVariableNameAndValue("{categoryId}", "34")
|
new TemplateVariableNameAndValue("{categoryId}", "34")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRoute("productservice/category/{categoryId}/products/{productId}/variants/{variantId}", "", "", "", false, ""))))
|
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}").Build())))
|
||||||
.When(x => x.WhenIReplaceTheTemplateVariables())
|
.When(x => x.WhenIReplaceTheTemplateVariables())
|
||||||
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12"))
|
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user