mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 22:08:17 +08:00
Rename all ReRoute to Route to move closer to YARP +semver: breaking
This commit is contained in:
@ -1,27 +1,27 @@
|
||||
namespace Ocelot.Provider.Consul
|
||||
{
|
||||
using Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ServiceDiscovery;
|
||||
|
||||
public static class ConsulProviderFactory
|
||||
{
|
||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, reRoute) =>
|
||||
{
|
||||
var factory = provider.GetService<IOcelotLoggerFactory>();
|
||||
|
||||
var consulFactory = provider.GetService<IConsulClientFactory>();
|
||||
|
||||
var consulRegistryConfiguration = new ConsulRegistryConfiguration(config.Scheme, config.Host, config.Port, reRoute.ServiceName, config.Token);
|
||||
|
||||
var consulServiceDiscoveryProvider = new Consul(consulRegistryConfiguration, factory, consulFactory);
|
||||
|
||||
if (config.Type?.ToLower() == "pollconsul")
|
||||
{
|
||||
return new PollConsul(config.PollingInterval, factory, consulServiceDiscoveryProvider);
|
||||
}
|
||||
|
||||
return consulServiceDiscoveryProvider;
|
||||
};
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Provider.Consul
|
||||
{
|
||||
using Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ServiceDiscovery;
|
||||
|
||||
public static class ConsulProviderFactory
|
||||
{
|
||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
|
||||
{
|
||||
var factory = provider.GetService<IOcelotLoggerFactory>();
|
||||
|
||||
var consulFactory = provider.GetService<IConsulClientFactory>();
|
||||
|
||||
var consulRegistryConfiguration = new ConsulRegistryConfiguration(config.Scheme, config.Host, config.Port, route.ServiceName, config.Token);
|
||||
|
||||
var consulServiceDiscoveryProvider = new Consul(consulRegistryConfiguration, factory, consulFactory);
|
||||
|
||||
if (config.Type?.ToLower() == "pollconsul")
|
||||
{
|
||||
return new PollConsul(config.PollingInterval, factory, consulServiceDiscoveryProvider);
|
||||
}
|
||||
|
||||
return consulServiceDiscoveryProvider;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
namespace Ocelot.Provider.Eureka
|
||||
{
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ServiceDiscovery;
|
||||
using Steeltoe.Common.Discovery;
|
||||
|
||||
public static class EurekaProviderFactory
|
||||
{
|
||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, reRoute) =>
|
||||
{
|
||||
var client = provider.GetService<IDiscoveryClient>();
|
||||
|
||||
if (config.Type?.ToLower() == "eureka" && client != null)
|
||||
{
|
||||
return new Eureka(reRoute.ServiceName, client);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Provider.Eureka
|
||||
{
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ServiceDiscovery;
|
||||
using Steeltoe.Common.Discovery;
|
||||
|
||||
public static class EurekaProviderFactory
|
||||
{
|
||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
|
||||
{
|
||||
var client = provider.GetService<IDiscoveryClient>();
|
||||
|
||||
if (config.Type?.ToLower() == "eureka" && client != null)
|
||||
{
|
||||
return new Eureka(route.ServiceName, client);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,37 @@
|
||||
using KubeClient;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
using System;
|
||||
using Ocelot.Configuration;
|
||||
|
||||
namespace Ocelot.Provider.Kubernetes
|
||||
{
|
||||
public static class KubernetesProviderFactory
|
||||
{
|
||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, reRoute) =>
|
||||
{
|
||||
var factory = provider.GetService<IOcelotLoggerFactory>();
|
||||
return GetKubeProvider(provider, config, reRoute, factory);
|
||||
};
|
||||
|
||||
private static ServiceDiscovery.Providers.IServiceDiscoveryProvider GetKubeProvider(IServiceProvider provider, ServiceProviderConfiguration config, DownstreamReRoute reRoute, IOcelotLoggerFactory factory)
|
||||
{
|
||||
var kubeClient = provider.GetService<IKubeApiClient>();
|
||||
|
||||
var k8sRegistryConfiguration = new KubeRegistryConfiguration()
|
||||
{
|
||||
KeyOfServiceInK8s = reRoute.ServiceName,
|
||||
KubeNamespace = string.IsNullOrEmpty(reRoute.ServiceNamespace) ? config.Namespace : reRoute.ServiceNamespace
|
||||
};
|
||||
|
||||
var k8sServiceDiscoveryProvider = new KubernetesServiceDiscoveryProvider(k8sRegistryConfiguration, factory, kubeClient);
|
||||
|
||||
if (config.Type?.ToLower() == "pollkube")
|
||||
{
|
||||
return new PollKubernetes(config.PollingInterval, factory, k8sServiceDiscoveryProvider);
|
||||
}
|
||||
return k8sServiceDiscoveryProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
using KubeClient;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
using System;
|
||||
using Ocelot.Configuration;
|
||||
|
||||
namespace Ocelot.Provider.Kubernetes
|
||||
{
|
||||
public static class KubernetesProviderFactory
|
||||
{
|
||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
|
||||
{
|
||||
var factory = provider.GetService<IOcelotLoggerFactory>();
|
||||
return GetKubeProvider(provider, config, route, factory);
|
||||
};
|
||||
|
||||
private static ServiceDiscovery.Providers.IServiceDiscoveryProvider GetKubeProvider(IServiceProvider provider, ServiceProviderConfiguration config, DownstreamRoute route, IOcelotLoggerFactory factory)
|
||||
{
|
||||
var kubeClient = provider.GetService<IKubeApiClient>();
|
||||
|
||||
var k8sRegistryConfiguration = new KubeRegistryConfiguration()
|
||||
{
|
||||
KeyOfServiceInK8s = route.ServiceName,
|
||||
KubeNamespace = string.IsNullOrEmpty(route.ServiceNamespace) ? config.Namespace : route.ServiceNamespace
|
||||
};
|
||||
|
||||
var k8sServiceDiscoveryProvider = new KubernetesServiceDiscoveryProvider(k8sRegistryConfiguration, factory, kubeClient);
|
||||
|
||||
if (config.Type?.ToLower() == "pollkube")
|
||||
{
|
||||
return new PollKubernetes(config.PollingInterval, factory, k8sServiceDiscoveryProvider);
|
||||
}
|
||||
return k8sServiceDiscoveryProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,38 @@
|
||||
namespace Ocelot.Provider.Polly
|
||||
{
|
||||
using Configuration;
|
||||
using DependencyInjection;
|
||||
using Errors;
|
||||
using global::Polly.CircuitBreaker;
|
||||
using global::Polly.Timeout;
|
||||
using Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Requester;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public static class OcelotBuilderExtensions
|
||||
{
|
||||
public static IOcelotBuilder AddPolly(this IOcelotBuilder builder)
|
||||
{
|
||||
var errorMapping = new Dictionary<Type, Func<Exception, Error>>
|
||||
{
|
||||
{typeof(TaskCanceledException), e => new RequestTimedOutError(e)},
|
||||
{typeof(TimeoutRejectedException), e => new RequestTimedOutError(e)},
|
||||
{typeof(BrokenCircuitException), e => new RequestTimedOutError(e)}
|
||||
};
|
||||
|
||||
builder.Services.AddSingleton(errorMapping);
|
||||
|
||||
DelegatingHandler QosDelegatingHandlerDelegate(DownstreamReRoute reRoute, IOcelotLoggerFactory logger)
|
||||
{
|
||||
return new PollyCircuitBreakingDelegatingHandler(new PollyQoSProvider(reRoute, logger), logger);
|
||||
}
|
||||
|
||||
builder.Services.AddSingleton((QosDelegatingHandlerDelegate)QosDelegatingHandlerDelegate);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Provider.Polly
|
||||
{
|
||||
using Configuration;
|
||||
using DependencyInjection;
|
||||
using Errors;
|
||||
using global::Polly.CircuitBreaker;
|
||||
using global::Polly.Timeout;
|
||||
using Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Requester;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public static class OcelotBuilderExtensions
|
||||
{
|
||||
public static IOcelotBuilder AddPolly(this IOcelotBuilder builder)
|
||||
{
|
||||
var errorMapping = new Dictionary<Type, Func<Exception, Error>>
|
||||
{
|
||||
{typeof(TaskCanceledException), e => new RequestTimedOutError(e)},
|
||||
{typeof(TimeoutRejectedException), e => new RequestTimedOutError(e)},
|
||||
{typeof(BrokenCircuitException), e => new RequestTimedOutError(e)}
|
||||
};
|
||||
|
||||
builder.Services.AddSingleton(errorMapping);
|
||||
|
||||
DelegatingHandler QosDelegatingHandlerDelegate(DownstreamRoute route, IOcelotLoggerFactory logger)
|
||||
{
|
||||
return new PollyCircuitBreakingDelegatingHandler(new PollyQoSProvider(route, logger), logger);
|
||||
}
|
||||
|
||||
builder.Services.AddSingleton((QosDelegatingHandlerDelegate)QosDelegatingHandlerDelegate);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
namespace Ocelot.Provider.Polly
|
||||
{
|
||||
using global::Polly;
|
||||
using global::Polly.CircuitBreaker;
|
||||
using global::Polly.Timeout;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Logging;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
public class PollyQoSProvider
|
||||
{
|
||||
private readonly AsyncCircuitBreakerPolicy _circuitBreakerPolicy;
|
||||
private readonly AsyncTimeoutPolicy _timeoutPolicy;
|
||||
private readonly IOcelotLogger _logger;
|
||||
|
||||
public PollyQoSProvider(DownstreamReRoute reRoute, IOcelotLoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();
|
||||
|
||||
Enum.TryParse(reRoute.QosOptions.TimeoutStrategy, out TimeoutStrategy strategy);
|
||||
|
||||
_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptions.TimeoutValue), strategy);
|
||||
|
||||
if (reRoute.QosOptions.ExceptionsAllowedBeforeBreaking > 0)
|
||||
{
|
||||
_circuitBreakerPolicy = Policy
|
||||
.Handle<HttpRequestException>()
|
||||
.Or<TimeoutRejectedException>()
|
||||
.Or<TimeoutException>()
|
||||
.CircuitBreakerAsync(
|
||||
exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking,
|
||||
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptions.DurationOfBreak),
|
||||
onBreak: (ex, breakDelay) =>
|
||||
{
|
||||
_logger.LogError(
|
||||
".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
|
||||
},
|
||||
onReset: () =>
|
||||
{
|
||||
_logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again.");
|
||||
},
|
||||
onHalfOpen: () =>
|
||||
{
|
||||
_logger.LogDebug(".Breaker logging: Half-open; next call is a trial.");
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_circuitBreakerPolicy = null;
|
||||
}
|
||||
|
||||
CircuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy);
|
||||
}
|
||||
|
||||
public CircuitBreaker CircuitBreaker { get; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Provider.Polly
|
||||
{
|
||||
using global::Polly;
|
||||
using global::Polly.CircuitBreaker;
|
||||
using global::Polly.Timeout;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Logging;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
public class PollyQoSProvider
|
||||
{
|
||||
private readonly AsyncCircuitBreakerPolicy _circuitBreakerPolicy;
|
||||
private readonly AsyncTimeoutPolicy _timeoutPolicy;
|
||||
private readonly IOcelotLogger _logger;
|
||||
|
||||
public PollyQoSProvider(DownstreamRoute route, IOcelotLoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();
|
||||
|
||||
Enum.TryParse(route.QosOptions.TimeoutStrategy, out TimeoutStrategy strategy);
|
||||
|
||||
_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(route.QosOptions.TimeoutValue), strategy);
|
||||
|
||||
if (route.QosOptions.ExceptionsAllowedBeforeBreaking > 0)
|
||||
{
|
||||
_circuitBreakerPolicy = Policy
|
||||
.Handle<HttpRequestException>()
|
||||
.Or<TimeoutRejectedException>()
|
||||
.Or<TimeoutException>()
|
||||
.CircuitBreakerAsync(
|
||||
exceptionsAllowedBeforeBreaking: route.QosOptions.ExceptionsAllowedBeforeBreaking,
|
||||
durationOfBreak: TimeSpan.FromMilliseconds(route.QosOptions.DurationOfBreak),
|
||||
onBreak: (ex, breakDelay) =>
|
||||
{
|
||||
_logger.LogError(
|
||||
".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
|
||||
},
|
||||
onReset: () =>
|
||||
{
|
||||
_logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again.");
|
||||
},
|
||||
onHalfOpen: () =>
|
||||
{
|
||||
_logger.LogDebug(".Breaker logging: Half-open; next call is a trial.");
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_circuitBreakerPolicy = null;
|
||||
}
|
||||
|
||||
CircuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy);
|
||||
}
|
||||
|
||||
public CircuitBreaker CircuitBreaker { get; }
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,13 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (httpContext.Request.Method.ToUpper() != "OPTIONS" && IsAuthenticatedRoute(downstreamReRoute))
|
||||
if (httpContext.Request.Method.ToUpper() != "OPTIONS" && IsAuthenticatedRoute(downstreamRoute))
|
||||
{
|
||||
Logger.LogInformation($"{httpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
|
||||
|
||||
var result = await httpContext.AuthenticateAsync(downstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
|
||||
var result = await httpContext.AuthenticateAsync(downstreamRoute.AuthenticationOptions.AuthenticationProviderKey);
|
||||
|
||||
httpContext.User = result.Principal;
|
||||
|
||||
@ -54,9 +54,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAuthenticatedRoute(DownstreamReRoute reRoute)
|
||||
private static bool IsAuthenticatedRoute(DownstreamRoute route)
|
||||
{
|
||||
return reRoute.IsAuthenticated;
|
||||
return route.IsAuthenticated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,13 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (!IsOptionsHttpMethod(httpContext) && IsAuthenticatedRoute(downstreamReRoute))
|
||||
if (!IsOptionsHttpMethod(httpContext) && IsAuthenticatedRoute(downstreamRoute))
|
||||
{
|
||||
Logger.LogInformation("route is authenticated scopes must be checked");
|
||||
|
||||
var authorised = _scopesAuthoriser.Authorise(httpContext.User, downstreamReRoute.AuthenticationOptions.AllowedScopes);
|
||||
var authorised = _scopesAuthoriser.Authorise(httpContext.User, downstreamRoute.AuthenticationOptions.AllowedScopes);
|
||||
|
||||
if (authorised.IsError)
|
||||
{
|
||||
@ -52,15 +52,15 @@
|
||||
Logger.LogWarning("user scopes is not authorised setting pipeline error");
|
||||
|
||||
httpContext.Items.SetError(new UnauthorisedError(
|
||||
$"{httpContext.User.Identity.Name} unable to access {downstreamReRoute.UpstreamPathTemplate.OriginalValue}"));
|
||||
$"{httpContext.User.Identity.Name} unable to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsOptionsHttpMethod(httpContext) && IsAuthorisedRoute(downstreamReRoute))
|
||||
if (!IsOptionsHttpMethod(httpContext) && IsAuthorisedRoute(downstreamRoute))
|
||||
{
|
||||
Logger.LogInformation("route is authorised");
|
||||
|
||||
var authorised = _claimsAuthoriser.Authorise(httpContext.User, downstreamReRoute.RouteClaimsRequirement, httpContext.Items.TemplatePlaceholderNameAndValues());
|
||||
var authorised = _claimsAuthoriser.Authorise(httpContext.User, downstreamRoute.RouteClaimsRequirement, httpContext.Items.TemplatePlaceholderNameAndValues());
|
||||
|
||||
if (authorised.IsError)
|
||||
{
|
||||
@ -72,19 +72,19 @@
|
||||
|
||||
if (IsAuthorised(authorised))
|
||||
{
|
||||
Logger.LogInformation($"{httpContext.User.Identity.Name} has succesfully been authorised for {downstreamReRoute.UpstreamPathTemplate.OriginalValue}.");
|
||||
Logger.LogInformation($"{httpContext.User.Identity.Name} has succesfully been authorised for {downstreamRoute.UpstreamPathTemplate.OriginalValue}.");
|
||||
await _next.Invoke(httpContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning($"{httpContext.User.Identity.Name} is not authorised to access {downstreamReRoute.UpstreamPathTemplate.OriginalValue}. Setting pipeline error");
|
||||
Logger.LogWarning($"{httpContext.User.Identity.Name} is not authorised to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}. Setting pipeline error");
|
||||
|
||||
httpContext.Items.SetError(new UnauthorisedError($"{httpContext.User.Identity.Name} is not authorised to access {downstreamReRoute.UpstreamPathTemplate.OriginalValue}"));
|
||||
httpContext.Items.SetError(new UnauthorisedError($"{httpContext.User.Identity.Name} is not authorised to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation($"{downstreamReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
|
||||
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
|
||||
await _next.Invoke(httpContext);
|
||||
}
|
||||
}
|
||||
@ -94,14 +94,14 @@
|
||||
return authorised.Data;
|
||||
}
|
||||
|
||||
private static bool IsAuthenticatedRoute(DownstreamReRoute reRoute)
|
||||
private static bool IsAuthenticatedRoute(DownstreamRoute route)
|
||||
{
|
||||
return reRoute.IsAuthenticated;
|
||||
return route.IsAuthenticated;
|
||||
}
|
||||
|
||||
private static bool IsAuthorisedRoute(DownstreamReRoute reRoute)
|
||||
private static bool IsAuthorisedRoute(DownstreamRoute route)
|
||||
{
|
||||
return reRoute.IsAuthorised;
|
||||
return route.IsAuthorised;
|
||||
}
|
||||
|
||||
private static bool IsOptionsHttpMethod(HttpContext httpContext)
|
||||
|
@ -4,6 +4,6 @@ namespace Ocelot.Cache
|
||||
{
|
||||
public interface IRegionCreator
|
||||
{
|
||||
string Create(FileReRoute reRoute);
|
||||
string Create(FileRoute route);
|
||||
}
|
||||
}
|
@ -1,129 +1,129 @@
|
||||
namespace Ocelot.Cache.Middleware
|
||||
{
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
namespace Ocelot.Cache.Middleware
|
||||
{
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class OutputCacheMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IOcelotCache<CachedResponse> _outputCache;
|
||||
private readonly ICacheKeyGenerator _cacheGenerator;
|
||||
|
||||
public OutputCacheMiddleware(RequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
IOcelotCache<CachedResponse> outputCache,
|
||||
ICacheKeyGenerator cacheGenerator)
|
||||
: base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
_outputCache = outputCache;
|
||||
_cacheGenerator = cacheGenerator;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
|
||||
if (!downstreamReRoute.IsCached)
|
||||
{
|
||||
await _next.Invoke(httpContext);
|
||||
return;
|
||||
public class OutputCacheMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IOcelotCache<CachedResponse> _outputCache;
|
||||
private readonly ICacheKeyGenerator _cacheGenerator;
|
||||
|
||||
public OutputCacheMiddleware(RequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
IOcelotCache<CachedResponse> outputCache,
|
||||
ICacheKeyGenerator cacheGenerator)
|
||||
: base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
_outputCache = outputCache;
|
||||
_cacheGenerator = cacheGenerator;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (!downstreamRoute.IsCached)
|
||||
{
|
||||
await _next.Invoke(httpContext);
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
var downstreamUrlKey = $"{downstreamRequest.Method}-{downstreamRequest.OriginalString}";
|
||||
string downStreamRequestCacheKey = _cacheGenerator.GenerateRequestCacheKey(downstreamRequest);
|
||||
|
||||
Logger.LogDebug($"Started checking cache for {downstreamUrlKey}");
|
||||
|
||||
var cached = _outputCache.Get(downStreamRequestCacheKey, downstreamReRoute.CacheOptions.Region);
|
||||
|
||||
if (cached != null)
|
||||
{
|
||||
Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
|
||||
|
||||
var response = CreateHttpResponseMessage(cached);
|
||||
SetHttpResponseMessageThisRequest(httpContext, response);
|
||||
|
||||
Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
|
||||
|
||||
await _next.Invoke(httpContext);
|
||||
|
||||
if (httpContext.Items.Errors().Count > 0)
|
||||
{
|
||||
Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
var downstreamUrlKey = $"{downstreamRequest.Method}-{downstreamRequest.OriginalString}";
|
||||
string downStreamRequestCacheKey = _cacheGenerator.GenerateRequestCacheKey(downstreamRequest);
|
||||
|
||||
Logger.LogDebug($"Started checking cache for {downstreamUrlKey}");
|
||||
|
||||
var cached = _outputCache.Get(downStreamRequestCacheKey, downstreamRoute.CacheOptions.Region);
|
||||
|
||||
if (cached != null)
|
||||
{
|
||||
Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
|
||||
|
||||
var response = CreateHttpResponseMessage(cached);
|
||||
SetHttpResponseMessageThisRequest(httpContext, response);
|
||||
|
||||
Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamResponse = httpContext.Items.DownstreamResponse();
|
||||
|
||||
cached = await CreateCachedResponse(downstreamResponse);
|
||||
|
||||
_outputCache.Add(downStreamRequestCacheKey, cached, TimeSpan.FromSeconds(downstreamReRoute.CacheOptions.TtlSeconds), downstreamReRoute.CacheOptions.Region);
|
||||
|
||||
Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
|
||||
}
|
||||
|
||||
private void SetHttpResponseMessageThisRequest(HttpContext context,
|
||||
DownstreamResponse response)
|
||||
{
|
||||
context.Items.UpsertDownstreamResponse(response);
|
||||
}
|
||||
|
||||
internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
|
||||
{
|
||||
if (cached == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = new MemoryStream(Convert.FromBase64String(cached.Body));
|
||||
|
||||
var streamContent = new StreamContent(content);
|
||||
|
||||
foreach (var header in cached.ContentHeaders)
|
||||
{
|
||||
streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
|
||||
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList(), cached.ReasonPhrase);
|
||||
}
|
||||
|
||||
internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var statusCode = response.StatusCode;
|
||||
var headers = response.Headers.ToDictionary(v => v.Key, v => v.Values);
|
||||
string body = null;
|
||||
|
||||
if (response.Content != null)
|
||||
{
|
||||
var content = await response.Content.ReadAsByteArrayAsync();
|
||||
body = Convert.ToBase64String(content);
|
||||
}
|
||||
|
||||
var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value);
|
||||
|
||||
var cached = new CachedResponse(statusCode, headers, body, contentHeaders, response.ReasonPhrase);
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
|
||||
|
||||
await _next.Invoke(httpContext);
|
||||
|
||||
if (httpContext.Items.Errors().Count > 0)
|
||||
{
|
||||
Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamResponse = httpContext.Items.DownstreamResponse();
|
||||
|
||||
cached = await CreateCachedResponse(downstreamResponse);
|
||||
|
||||
_outputCache.Add(downStreamRequestCacheKey, cached, TimeSpan.FromSeconds(downstreamRoute.CacheOptions.TtlSeconds), downstreamRoute.CacheOptions.Region);
|
||||
|
||||
Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
|
||||
}
|
||||
|
||||
private void SetHttpResponseMessageThisRequest(HttpContext context,
|
||||
DownstreamResponse response)
|
||||
{
|
||||
context.Items.UpsertDownstreamResponse(response);
|
||||
}
|
||||
|
||||
internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
|
||||
{
|
||||
if (cached == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = new MemoryStream(Convert.FromBase64String(cached.Body));
|
||||
|
||||
var streamContent = new StreamContent(content);
|
||||
|
||||
foreach (var header in cached.ContentHeaders)
|
||||
{
|
||||
streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
|
||||
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList(), cached.ReasonPhrase);
|
||||
}
|
||||
|
||||
internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var statusCode = response.StatusCode;
|
||||
var headers = response.Headers.ToDictionary(v => v.Key, v => v.Values);
|
||||
string body = null;
|
||||
|
||||
if (response.Content != null)
|
||||
{
|
||||
var content = await response.Content.ReadAsByteArrayAsync();
|
||||
body = Convert.ToBase64String(content);
|
||||
}
|
||||
|
||||
var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value);
|
||||
|
||||
var cached = new CachedResponse(statusCode, headers, body, contentHeaders, response.ReasonPhrase);
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,18 @@ namespace Ocelot.Cache
|
||||
{
|
||||
public class RegionCreator : IRegionCreator
|
||||
{
|
||||
public string Create(FileReRoute reRoute)
|
||||
public string Create(FileRoute route)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(reRoute?.FileCacheOptions?.Region))
|
||||
if (!string.IsNullOrEmpty(route?.FileCacheOptions?.Region))
|
||||
{
|
||||
return reRoute?.FileCacheOptions?.Region;
|
||||
return route?.FileCacheOptions?.Region;
|
||||
}
|
||||
|
||||
var methods = string.Join("", reRoute.UpstreamHttpMethod.Select(m => m));
|
||||
var methods = string.Join("", route.UpstreamHttpMethod.Select(m => m));
|
||||
|
||||
var region = $"{methods}{route.UpstreamPathTemplate.Replace("/", "")}";
|
||||
|
||||
var region = $"{methods}{reRoute.UpstreamPathTemplate.Replace("/", "")}";
|
||||
|
||||
return region;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace Ocelot.Claims.Middleware
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System.Linq;
|
||||
@ -23,13 +23,13 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (downstreamReRoute.ClaimsToClaims.Any())
|
||||
if (downstreamRoute.ClaimsToClaims.Any())
|
||||
{
|
||||
Logger.LogDebug("this route has instructions to convert claims to other claims");
|
||||
|
||||
var result = _addClaimsToRequest.SetClaimsOnContext(downstreamReRoute.ClaimsToClaims, httpContext);
|
||||
var result = _addClaimsToRequest.SetClaimsOnContext(downstreamRoute.ClaimsToClaims, httpContext);
|
||||
|
||||
if (result.IsError)
|
||||
{
|
||||
|
@ -1,305 +1,305 @@
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Values;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class DownstreamReRouteBuilder
|
||||
{
|
||||
private AuthenticationOptions _authenticationOptions;
|
||||
private string _loadBalancerKey;
|
||||
private string _downstreamPathTemplate;
|
||||
private UpstreamPathTemplate _upstreamTemplatePattern;
|
||||
private List<HttpMethod> _upstreamHttpMethod;
|
||||
private bool _isAuthenticated;
|
||||
private List<ClaimToThing> _claimsToHeaders;
|
||||
private List<ClaimToThing> _claimToClaims;
|
||||
private Dictionary<string, string> _routeClaimRequirement;
|
||||
private bool _isAuthorised;
|
||||
private List<ClaimToThing> _claimToQueries;
|
||||
private List<ClaimToThing> _claimToDownstreamPath;
|
||||
private string _requestIdHeaderKey;
|
||||
private bool _isCached;
|
||||
private CacheOptions _fileCacheOptions;
|
||||
private string _downstreamScheme;
|
||||
private LoadBalancerOptions _loadBalancerOptions;
|
||||
private QoSOptions _qosOptions;
|
||||
private HttpHandlerOptions _httpHandlerOptions;
|
||||
private bool _enableRateLimiting;
|
||||
private RateLimitOptions _rateLimitOptions;
|
||||
private bool _useServiceDiscovery;
|
||||
private string _serviceName;
|
||||
private string _serviceNamespace;
|
||||
private List<HeaderFindAndReplace> _upstreamHeaderFindAndReplace;
|
||||
private List<HeaderFindAndReplace> _downstreamHeaderFindAndReplace;
|
||||
private readonly List<DownstreamHostAndPort> _downstreamAddresses;
|
||||
private string _key;
|
||||
private List<string> _delegatingHandlers;
|
||||
private List<AddHeader> _addHeadersToDownstream;
|
||||
private List<AddHeader> _addHeadersToUpstream;
|
||||
private bool _dangerousAcceptAnyServerCertificateValidator;
|
||||
private SecurityOptions _securityOptions;
|
||||
private string _downstreamHttpMethod;
|
||||
private Version _downstreamHttpVersion;
|
||||
|
||||
public DownstreamReRouteBuilder()
|
||||
{
|
||||
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
||||
_delegatingHandlers = new List<string>();
|
||||
_addHeadersToDownstream = new List<AddHeader>();
|
||||
_addHeadersToUpstream = new List<AddHeader>();
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
||||
{
|
||||
_downstreamAddresses.AddRange(downstreamAddresses);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownStreamHttpMethod(string method)
|
||||
{
|
||||
_downstreamHttpMethod = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions)
|
||||
{
|
||||
_loadBalancerOptions = loadBalancerOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownstreamScheme(string downstreamScheme)
|
||||
{
|
||||
_downstreamScheme = downstreamScheme;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownstreamPathTemplate(string input)
|
||||
{
|
||||
_downstreamPathTemplate = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithUpstreamPathTemplate(UpstreamPathTemplate input)
|
||||
{
|
||||
_upstreamTemplatePattern = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithUpstreamHttpMethod(List<string> input)
|
||||
{
|
||||
_upstreamHttpMethod = (input.Count == 0) ? new List<HttpMethod>() : input.Select(x => new HttpMethod(x.Trim())).ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithIsAuthenticated(bool input)
|
||||
{
|
||||
_isAuthenticated = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithIsAuthorised(bool input)
|
||||
{
|
||||
_isAuthorised = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithRequestIdKey(string input)
|
||||
{
|
||||
_requestIdHeaderKey = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithClaimsToHeaders(List<ClaimToThing> input)
|
||||
{
|
||||
_claimsToHeaders = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithClaimsToClaims(List<ClaimToThing> input)
|
||||
{
|
||||
_claimToClaims = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithRouteClaimsRequirement(Dictionary<string, string> input)
|
||||
{
|
||||
_routeClaimRequirement = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithClaimsToQueries(List<ClaimToThing> input)
|
||||
{
|
||||
_claimToQueries = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithClaimsToDownstreamPath(List<ClaimToThing> input)
|
||||
{
|
||||
_claimToDownstreamPath = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithIsCached(bool input)
|
||||
{
|
||||
_isCached = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithCacheOptions(CacheOptions input)
|
||||
{
|
||||
_fileCacheOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithQosOptions(QoSOptions input)
|
||||
{
|
||||
_qosOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
|
||||
{
|
||||
_loadBalancerKey = loadBalancerKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithAuthenticationOptions(AuthenticationOptions authenticationOptions)
|
||||
{
|
||||
_authenticationOptions = authenticationOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithEnableRateLimiting(bool input)
|
||||
{
|
||||
_enableRateLimiting = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithRateLimitOptions(RateLimitOptions input)
|
||||
{
|
||||
_rateLimitOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithHttpHandlerOptions(HttpHandlerOptions input)
|
||||
{
|
||||
_httpHandlerOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
|
||||
{
|
||||
_useServiceDiscovery = useServiceDiscovery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithServiceName(string serviceName)
|
||||
{
|
||||
_serviceName = serviceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithServiceNamespace(string serviceNamespace)
|
||||
{
|
||||
_serviceNamespace = serviceNamespace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithUpstreamHeaderFindAndReplace(List<HeaderFindAndReplace> upstreamHeaderFindAndReplace)
|
||||
{
|
||||
_upstreamHeaderFindAndReplace = upstreamHeaderFindAndReplace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownstreamHeaderFindAndReplace(List<HeaderFindAndReplace> downstreamHeaderFindAndReplace)
|
||||
{
|
||||
_downstreamHeaderFindAndReplace = downstreamHeaderFindAndReplace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithKey(string key)
|
||||
{
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDelegatingHandlers(List<string> delegatingHandlers)
|
||||
{
|
||||
_delegatingHandlers = delegatingHandlers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithAddHeadersToDownstream(List<AddHeader> addHeadersToDownstream)
|
||||
{
|
||||
_addHeadersToDownstream = addHeadersToDownstream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithAddHeadersToUpstream(List<AddHeader> addHeadersToUpstream)
|
||||
{
|
||||
_addHeadersToUpstream = addHeadersToUpstream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDangerousAcceptAnyServerCertificateValidator(bool dangerousAcceptAnyServerCertificateValidator)
|
||||
{
|
||||
_dangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithSecurityOptions(SecurityOptions securityOptions)
|
||||
{
|
||||
_securityOptions = securityOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownstreamHttpVersion(Version downstreamHttpVersion)
|
||||
{
|
||||
_downstreamHttpVersion = downstreamHttpVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRoute Build()
|
||||
{
|
||||
return new DownstreamReRoute(
|
||||
_key,
|
||||
_upstreamTemplatePattern,
|
||||
_upstreamHeaderFindAndReplace,
|
||||
_downstreamHeaderFindAndReplace,
|
||||
_downstreamAddresses,
|
||||
_serviceName,
|
||||
_serviceNamespace,
|
||||
_httpHandlerOptions,
|
||||
_useServiceDiscovery,
|
||||
_enableRateLimiting,
|
||||
_qosOptions,
|
||||
_downstreamScheme,
|
||||
_requestIdHeaderKey,
|
||||
_isCached,
|
||||
_fileCacheOptions,
|
||||
_loadBalancerOptions,
|
||||
_rateLimitOptions,
|
||||
_routeClaimRequirement,
|
||||
_claimToQueries,
|
||||
_claimsToHeaders,
|
||||
_claimToClaims,
|
||||
_claimToDownstreamPath,
|
||||
_isAuthenticated,
|
||||
_isAuthorised,
|
||||
_authenticationOptions,
|
||||
new DownstreamPathTemplate(_downstreamPathTemplate),
|
||||
_loadBalancerKey,
|
||||
_delegatingHandlers,
|
||||
_addHeadersToDownstream,
|
||||
_addHeadersToUpstream,
|
||||
_dangerousAcceptAnyServerCertificateValidator,
|
||||
_securityOptions,
|
||||
_downstreamHttpMethod,
|
||||
_downstreamHttpVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Values;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class DownstreamRouteBuilder
|
||||
{
|
||||
private AuthenticationOptions _authenticationOptions;
|
||||
private string _loadBalancerKey;
|
||||
private string _downstreamPathTemplate;
|
||||
private UpstreamPathTemplate _upstreamTemplatePattern;
|
||||
private List<HttpMethod> _upstreamHttpMethod;
|
||||
private bool _isAuthenticated;
|
||||
private List<ClaimToThing> _claimsToHeaders;
|
||||
private List<ClaimToThing> _claimToClaims;
|
||||
private Dictionary<string, string> _routeClaimRequirement;
|
||||
private bool _isAuthorised;
|
||||
private List<ClaimToThing> _claimToQueries;
|
||||
private List<ClaimToThing> _claimToDownstreamPath;
|
||||
private string _requestIdHeaderKey;
|
||||
private bool _isCached;
|
||||
private CacheOptions _fileCacheOptions;
|
||||
private string _downstreamScheme;
|
||||
private LoadBalancerOptions _loadBalancerOptions;
|
||||
private QoSOptions _qosOptions;
|
||||
private HttpHandlerOptions _httpHandlerOptions;
|
||||
private bool _enableRateLimiting;
|
||||
private RateLimitOptions _rateLimitOptions;
|
||||
private bool _useServiceDiscovery;
|
||||
private string _serviceName;
|
||||
private string _serviceNamespace;
|
||||
private List<HeaderFindAndReplace> _upstreamHeaderFindAndReplace;
|
||||
private List<HeaderFindAndReplace> _downstreamHeaderFindAndReplace;
|
||||
private readonly List<DownstreamHostAndPort> _downstreamAddresses;
|
||||
private string _key;
|
||||
private List<string> _delegatingHandlers;
|
||||
private List<AddHeader> _addHeadersToDownstream;
|
||||
private List<AddHeader> _addHeadersToUpstream;
|
||||
private bool _dangerousAcceptAnyServerCertificateValidator;
|
||||
private SecurityOptions _securityOptions;
|
||||
private string _downstreamHttpMethod;
|
||||
private Version _downstreamHttpVersion;
|
||||
|
||||
public DownstreamRouteBuilder()
|
||||
{
|
||||
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
||||
_delegatingHandlers = new List<string>();
|
||||
_addHeadersToDownstream = new List<AddHeader>();
|
||||
_addHeadersToUpstream = new List<AddHeader>();
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
||||
{
|
||||
_downstreamAddresses.AddRange(downstreamAddresses);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDownStreamHttpMethod(string method)
|
||||
{
|
||||
_downstreamHttpMethod = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions)
|
||||
{
|
||||
_loadBalancerOptions = loadBalancerOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDownstreamScheme(string downstreamScheme)
|
||||
{
|
||||
_downstreamScheme = downstreamScheme;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDownstreamPathTemplate(string input)
|
||||
{
|
||||
_downstreamPathTemplate = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithUpstreamPathTemplate(UpstreamPathTemplate input)
|
||||
{
|
||||
_upstreamTemplatePattern = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithUpstreamHttpMethod(List<string> input)
|
||||
{
|
||||
_upstreamHttpMethod = (input.Count == 0) ? new List<HttpMethod>() : input.Select(x => new HttpMethod(x.Trim())).ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithIsAuthenticated(bool input)
|
||||
{
|
||||
_isAuthenticated = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithIsAuthorised(bool input)
|
||||
{
|
||||
_isAuthorised = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithRequestIdKey(string input)
|
||||
{
|
||||
_requestIdHeaderKey = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithClaimsToHeaders(List<ClaimToThing> input)
|
||||
{
|
||||
_claimsToHeaders = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithClaimsToClaims(List<ClaimToThing> input)
|
||||
{
|
||||
_claimToClaims = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithRouteClaimsRequirement(Dictionary<string, string> input)
|
||||
{
|
||||
_routeClaimRequirement = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithClaimsToQueries(List<ClaimToThing> input)
|
||||
{
|
||||
_claimToQueries = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithClaimsToDownstreamPath(List<ClaimToThing> input)
|
||||
{
|
||||
_claimToDownstreamPath = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithIsCached(bool input)
|
||||
{
|
||||
_isCached = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithCacheOptions(CacheOptions input)
|
||||
{
|
||||
_fileCacheOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithQosOptions(QoSOptions input)
|
||||
{
|
||||
_qosOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
|
||||
{
|
||||
_loadBalancerKey = loadBalancerKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithAuthenticationOptions(AuthenticationOptions authenticationOptions)
|
||||
{
|
||||
_authenticationOptions = authenticationOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithEnableRateLimiting(bool input)
|
||||
{
|
||||
_enableRateLimiting = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithRateLimitOptions(RateLimitOptions input)
|
||||
{
|
||||
_rateLimitOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithHttpHandlerOptions(HttpHandlerOptions input)
|
||||
{
|
||||
_httpHandlerOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
|
||||
{
|
||||
_useServiceDiscovery = useServiceDiscovery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithServiceName(string serviceName)
|
||||
{
|
||||
_serviceName = serviceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithServiceNamespace(string serviceNamespace)
|
||||
{
|
||||
_serviceNamespace = serviceNamespace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithUpstreamHeaderFindAndReplace(List<HeaderFindAndReplace> upstreamHeaderFindAndReplace)
|
||||
{
|
||||
_upstreamHeaderFindAndReplace = upstreamHeaderFindAndReplace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDownstreamHeaderFindAndReplace(List<HeaderFindAndReplace> downstreamHeaderFindAndReplace)
|
||||
{
|
||||
_downstreamHeaderFindAndReplace = downstreamHeaderFindAndReplace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithKey(string key)
|
||||
{
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDelegatingHandlers(List<string> delegatingHandlers)
|
||||
{
|
||||
_delegatingHandlers = delegatingHandlers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithAddHeadersToDownstream(List<AddHeader> addHeadersToDownstream)
|
||||
{
|
||||
_addHeadersToDownstream = addHeadersToDownstream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithAddHeadersToUpstream(List<AddHeader> addHeadersToUpstream)
|
||||
{
|
||||
_addHeadersToUpstream = addHeadersToUpstream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDangerousAcceptAnyServerCertificateValidator(bool dangerousAcceptAnyServerCertificateValidator)
|
||||
{
|
||||
_dangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithSecurityOptions(SecurityOptions securityOptions)
|
||||
{
|
||||
_securityOptions = securityOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRouteBuilder WithDownstreamHttpVersion(Version downstreamHttpVersion)
|
||||
{
|
||||
_downstreamHttpVersion = downstreamHttpVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamRoute Build()
|
||||
{
|
||||
return new DownstreamRoute(
|
||||
_key,
|
||||
_upstreamTemplatePattern,
|
||||
_upstreamHeaderFindAndReplace,
|
||||
_downstreamHeaderFindAndReplace,
|
||||
_downstreamAddresses,
|
||||
_serviceName,
|
||||
_serviceNamespace,
|
||||
_httpHandlerOptions,
|
||||
_useServiceDiscovery,
|
||||
_enableRateLimiting,
|
||||
_qosOptions,
|
||||
_downstreamScheme,
|
||||
_requestIdHeaderKey,
|
||||
_isCached,
|
||||
_fileCacheOptions,
|
||||
_loadBalancerOptions,
|
||||
_rateLimitOptions,
|
||||
_routeClaimRequirement,
|
||||
_claimToQueries,
|
||||
_claimsToHeaders,
|
||||
_claimToClaims,
|
||||
_claimToDownstreamPath,
|
||||
_isAuthenticated,
|
||||
_isAuthorised,
|
||||
_authenticationOptions,
|
||||
new DownstreamPathTemplate(_downstreamPathTemplate),
|
||||
_loadBalancerKey,
|
||||
_delegatingHandlers,
|
||||
_addHeadersToDownstream,
|
||||
_addHeadersToUpstream,
|
||||
_dangerousAcceptAnyServerCertificateValidator,
|
||||
_securityOptions,
|
||||
_downstreamHttpMethod,
|
||||
_downstreamHttpVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class QoSOptionsBuilder
|
||||
{
|
||||
private int _exceptionsAllowedBeforeBreaking;
|
||||
|
||||
private int _durationOfBreak;
|
||||
|
||||
private int _timeoutValue;
|
||||
|
||||
private string _key;
|
||||
|
||||
public QoSOptionsBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
|
||||
{
|
||||
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithDurationOfBreak(int durationOfBreak)
|
||||
{
|
||||
_durationOfBreak = durationOfBreak;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithTimeoutValue(int timeoutValue)
|
||||
{
|
||||
_timeoutValue = timeoutValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithKey(string input)
|
||||
{
|
||||
_key = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptions Build()
|
||||
{
|
||||
return new QoSOptions(_exceptionsAllowedBeforeBreaking, _durationOfBreak, _timeoutValue, _key);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class QoSOptionsBuilder
|
||||
{
|
||||
private int _exceptionsAllowedBeforeBreaking;
|
||||
|
||||
private int _durationOfBreak;
|
||||
|
||||
private int _timeoutValue;
|
||||
|
||||
private string _key;
|
||||
|
||||
public QoSOptionsBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
|
||||
{
|
||||
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithDurationOfBreak(int durationOfBreak)
|
||||
{
|
||||
_durationOfBreak = durationOfBreak;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithTimeoutValue(int timeoutValue)
|
||||
{
|
||||
_timeoutValue = timeoutValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithKey(string input)
|
||||
{
|
||||
_key = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptions Build()
|
||||
{
|
||||
return new QoSOptions(_exceptionsAllowedBeforeBreaking, _durationOfBreak, _timeoutValue, _key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Values;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
public class ReRouteBuilder
|
||||
{
|
||||
private UpstreamPathTemplate _upstreamTemplatePattern;
|
||||
private List<HttpMethod> _upstreamHttpMethod;
|
||||
private string _upstreamHost;
|
||||
private List<DownstreamReRoute> _downstreamReRoutes;
|
||||
private List<AggregateReRouteConfig> _downstreamReRoutesConfig;
|
||||
private string _aggregator;
|
||||
|
||||
public ReRouteBuilder()
|
||||
{
|
||||
_downstreamReRoutes = new List<DownstreamReRoute>();
|
||||
_downstreamReRoutesConfig = new List<AggregateReRouteConfig>();
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithDownstreamReRoute(DownstreamReRoute value)
|
||||
{
|
||||
_downstreamReRoutes.Add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithDownstreamReRoutes(List<DownstreamReRoute> value)
|
||||
{
|
||||
_downstreamReRoutes = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithUpstreamHost(string upstreamAddresses)
|
||||
{
|
||||
_upstreamHost = upstreamAddresses;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithUpstreamPathTemplate(UpstreamPathTemplate input)
|
||||
{
|
||||
_upstreamTemplatePattern = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithUpstreamHttpMethod(List<string> input)
|
||||
{
|
||||
_upstreamHttpMethod = (input.Count == 0) ? new List<HttpMethod>() : input.Select(x => new HttpMethod(x.Trim())).ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithAggregateReRouteConfig(List<AggregateReRouteConfig> aggregateReRouteConfigs)
|
||||
{
|
||||
_downstreamReRoutesConfig = aggregateReRouteConfigs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteBuilder WithAggregator(string aggregator)
|
||||
{
|
||||
_aggregator = aggregator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRoute Build()
|
||||
{
|
||||
return new ReRoute(
|
||||
_downstreamReRoutes,
|
||||
_downstreamReRoutesConfig,
|
||||
_upstreamHttpMethod,
|
||||
_upstreamTemplatePattern,
|
||||
_upstreamHost,
|
||||
_aggregator
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
78
src/Ocelot/Configuration/Builder/RouteBuilder.cs
Normal file
78
src/Ocelot/Configuration/Builder/RouteBuilder.cs
Normal file
@ -0,0 +1,78 @@
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Values;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
public class RouteBuilder
|
||||
{
|
||||
private UpstreamPathTemplate _upstreamTemplatePattern;
|
||||
private List<HttpMethod> _upstreamHttpMethod;
|
||||
private string _upstreamHost;
|
||||
private List<DownstreamRoute> _downstreamRoutes;
|
||||
private List<AggregateRouteConfig> _downstreamRoutesConfig;
|
||||
private string _aggregator;
|
||||
|
||||
public RouteBuilder()
|
||||
{
|
||||
_downstreamRoutes = new List<DownstreamRoute>();
|
||||
_downstreamRoutesConfig = new List<AggregateRouteConfig>();
|
||||
}
|
||||
|
||||
public RouteBuilder WithDownstreamRoute(DownstreamRoute value)
|
||||
{
|
||||
_downstreamRoutes.Add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteBuilder WithDownstreamRoutes(List<DownstreamRoute> value)
|
||||
{
|
||||
_downstreamRoutes = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteBuilder WithUpstreamHost(string upstreamAddresses)
|
||||
{
|
||||
_upstreamHost = upstreamAddresses;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteBuilder WithUpstreamPathTemplate(UpstreamPathTemplate input)
|
||||
{
|
||||
_upstreamTemplatePattern = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteBuilder WithUpstreamHttpMethod(List<string> input)
|
||||
{
|
||||
_upstreamHttpMethod = (input.Count == 0) ? new List<HttpMethod>() : input.Select(x => new HttpMethod(x.Trim())).ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteBuilder WithAggregateRouteConfig(List<AggregateRouteConfig> aggregateRouteConfigs)
|
||||
{
|
||||
_downstreamRoutesConfig = aggregateRouteConfigs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteBuilder WithAggregator(string aggregator)
|
||||
{
|
||||
_aggregator = aggregator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Route Build()
|
||||
{
|
||||
return new Route(
|
||||
_downstreamRoutes,
|
||||
_downstreamRoutesConfig,
|
||||
_upstreamHttpMethod,
|
||||
_upstreamTemplatePattern,
|
||||
_upstreamHost,
|
||||
_aggregator
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +1,46 @@
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class ReRouteOptionsBuilder
|
||||
{
|
||||
private bool _isAuthenticated;
|
||||
private bool _isAuthorised;
|
||||
private bool _isCached;
|
||||
private bool _enableRateLimiting;
|
||||
private bool _useServiceDiscovery;
|
||||
|
||||
public ReRouteOptionsBuilder WithIsCached(bool isCached)
|
||||
{
|
||||
_isCached = isCached;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithIsAuthenticated(bool isAuthenticated)
|
||||
{
|
||||
_isAuthenticated = isAuthenticated;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithIsAuthorised(bool isAuthorised)
|
||||
{
|
||||
_isAuthorised = isAuthorised;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
|
||||
{
|
||||
_enableRateLimiting = enableRateLimiting;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
|
||||
{
|
||||
_useServiceDiscovery = useServiceDiscovery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptions Build()
|
||||
{
|
||||
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting, _useServiceDiscovery);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Builder
|
||||
{
|
||||
public class RouteOptionsBuilder
|
||||
{
|
||||
private bool _isAuthenticated;
|
||||
private bool _isAuthorised;
|
||||
private bool _isCached;
|
||||
private bool _enableRateLimiting;
|
||||
private bool _useServiceDiscovery;
|
||||
|
||||
public RouteOptionsBuilder WithIsCached(bool isCached)
|
||||
{
|
||||
_isCached = isCached;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteOptionsBuilder WithIsAuthenticated(bool isAuthenticated)
|
||||
{
|
||||
_isAuthenticated = isAuthenticated;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteOptionsBuilder WithIsAuthorised(bool isAuthorised)
|
||||
{
|
||||
_isAuthorised = isAuthorised;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
|
||||
{
|
||||
_enableRateLimiting = enableRateLimiting;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteOptionsBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
|
||||
{
|
||||
_useServiceDiscovery = useServiceDiscovery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RouteOptions Build()
|
||||
{
|
||||
return new RouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting, _useServiceDiscovery);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +1,55 @@
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Builder;
|
||||
using File;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class AggregatesCreator : IAggregatesCreator
|
||||
{
|
||||
private readonly IUpstreamTemplatePatternCreator _creator;
|
||||
|
||||
public AggregatesCreator(IUpstreamTemplatePatternCreator creator)
|
||||
{
|
||||
_creator = creator;
|
||||
}
|
||||
|
||||
public List<ReRoute> Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes)
|
||||
{
|
||||
return fileConfiguration.Aggregates
|
||||
.Select(aggregate => SetUpAggregateReRoute(reRoutes, aggregate, fileConfiguration.GlobalConfiguration))
|
||||
.Where(aggregate => aggregate != null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private ReRoute SetUpAggregateReRoute(IEnumerable<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var applicableReRoutes = new List<DownstreamReRoute>();
|
||||
var allReRoutes = reRoutes.SelectMany(x => x.DownstreamReRoute);
|
||||
|
||||
foreach (var reRouteKey in aggregateReRoute.ReRouteKeys)
|
||||
{
|
||||
var selec = allReRoutes.FirstOrDefault(q => q.Key == reRouteKey);
|
||||
if (selec == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
applicableReRoutes.Add(selec);
|
||||
}
|
||||
|
||||
var upstreamTemplatePattern = _creator.Create(aggregateReRoute);
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(aggregateReRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamPathTemplate(upstreamTemplatePattern)
|
||||
.WithDownstreamReRoutes(applicableReRoutes)
|
||||
.WithAggregateReRouteConfig(aggregateReRoute.ReRouteKeysConfig)
|
||||
.WithUpstreamHost(aggregateReRoute.UpstreamHost)
|
||||
.WithAggregator(aggregateReRoute.Aggregator)
|
||||
.Build();
|
||||
|
||||
return reRoute;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Builder;
|
||||
using File;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class AggregatesCreator : IAggregatesCreator
|
||||
{
|
||||
private readonly IUpstreamTemplatePatternCreator _creator;
|
||||
|
||||
public AggregatesCreator(IUpstreamTemplatePatternCreator creator)
|
||||
{
|
||||
_creator = creator;
|
||||
}
|
||||
|
||||
public List<Route> Create(FileConfiguration fileConfiguration, List<Route> routes)
|
||||
{
|
||||
return fileConfiguration.Aggregates
|
||||
.Select(aggregate => SetUpAggregateRoute(routes, aggregate, fileConfiguration.GlobalConfiguration))
|
||||
.Where(aggregate => aggregate != null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private Route SetUpAggregateRoute(IEnumerable<Route> routes, FileAggregateRoute aggregateRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var applicableRoutes = new List<DownstreamRoute>();
|
||||
var allRoutes = routes.SelectMany(x => x.DownstreamRoute);
|
||||
|
||||
foreach (var routeKey in aggregateRoute.RouteKeys)
|
||||
{
|
||||
var selec = allRoutes.FirstOrDefault(q => q.Key == routeKey);
|
||||
if (selec == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
applicableRoutes.Add(selec);
|
||||
}
|
||||
|
||||
var upstreamTemplatePattern = _creator.Create(aggregateRoute);
|
||||
|
||||
var route = new RouteBuilder()
|
||||
.WithUpstreamHttpMethod(aggregateRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamPathTemplate(upstreamTemplatePattern)
|
||||
.WithDownstreamRoutes(applicableRoutes)
|
||||
.WithAggregateRouteConfig(aggregateRoute.RouteKeysConfig)
|
||||
.WithUpstreamHost(aggregateRoute.UpstreamHost)
|
||||
.WithAggregator(aggregateRoute.Aggregator)
|
||||
.Build();
|
||||
|
||||
return route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class AuthenticationOptionsCreator : IAuthenticationOptionsCreator
|
||||
{
|
||||
public AuthenticationOptions Create(FileReRoute reRoute)
|
||||
public AuthenticationOptions Create(FileRoute route)
|
||||
{
|
||||
return new AuthenticationOptions(reRoute.AuthenticationOptions.AllowedScopes, reRoute.AuthenticationOptions.AuthenticationProviderKey);
|
||||
}
|
||||
return new AuthenticationOptions(route.AuthenticationOptions.AllowedScopes, route.AuthenticationOptions.AuthenticationProviderKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,61 @@
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using DependencyInjection;
|
||||
using File;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ConfigurationCreator : IConfigurationCreator
|
||||
{
|
||||
private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
|
||||
private readonly IQoSOptionsCreator _qosOptionsCreator;
|
||||
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
|
||||
private readonly IAdministrationPath _adminPath;
|
||||
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
|
||||
private readonly IVersionCreator _versionCreator;
|
||||
|
||||
public ConfigurationCreator(
|
||||
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
||||
IQoSOptionsCreator qosOptionsCreator,
|
||||
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
|
||||
IServiceProvider serviceProvider,
|
||||
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
|
||||
IVersionCreator versionCreator
|
||||
)
|
||||
{
|
||||
_adminPath = serviceProvider.GetService<IAdministrationPath>();
|
||||
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
|
||||
_serviceProviderConfigCreator = serviceProviderConfigCreator;
|
||||
_qosOptionsCreator = qosOptionsCreator;
|
||||
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
|
||||
_versionCreator = versionCreator;
|
||||
}
|
||||
|
||||
public InternalConfiguration Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes)
|
||||
{
|
||||
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
|
||||
|
||||
var lbOptions = _loadBalancerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);
|
||||
|
||||
var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);
|
||||
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);
|
||||
|
||||
var adminPath = _adminPath != null ? _adminPath.Path : null;
|
||||
|
||||
var version = _versionCreator.Create(fileConfiguration.GlobalConfiguration.DownstreamHttpVersion);
|
||||
|
||||
return new InternalConfiguration(reRoutes,
|
||||
adminPath,
|
||||
serviceProviderConfiguration,
|
||||
fileConfiguration.GlobalConfiguration.RequestIdKey,
|
||||
lbOptions,
|
||||
fileConfiguration.GlobalConfiguration.DownstreamScheme,
|
||||
qosOptions,
|
||||
httpHandlerOptions,
|
||||
version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using DependencyInjection;
|
||||
using File;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ConfigurationCreator : IConfigurationCreator
|
||||
{
|
||||
private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
|
||||
private readonly IQoSOptionsCreator _qosOptionsCreator;
|
||||
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
|
||||
private readonly IAdministrationPath _adminPath;
|
||||
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
|
||||
private readonly IVersionCreator _versionCreator;
|
||||
|
||||
public ConfigurationCreator(
|
||||
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
||||
IQoSOptionsCreator qosOptionsCreator,
|
||||
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
|
||||
IServiceProvider serviceProvider,
|
||||
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
|
||||
IVersionCreator versionCreator
|
||||
)
|
||||
{
|
||||
_adminPath = serviceProvider.GetService<IAdministrationPath>();
|
||||
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
|
||||
_serviceProviderConfigCreator = serviceProviderConfigCreator;
|
||||
_qosOptionsCreator = qosOptionsCreator;
|
||||
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
|
||||
_versionCreator = versionCreator;
|
||||
}
|
||||
|
||||
public InternalConfiguration Create(FileConfiguration fileConfiguration, List<Route> routes)
|
||||
{
|
||||
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
|
||||
|
||||
var lbOptions = _loadBalancerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);
|
||||
|
||||
var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);
|
||||
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);
|
||||
|
||||
var adminPath = _adminPath != null ? _adminPath.Path : null;
|
||||
|
||||
var version = _versionCreator.Create(fileConfiguration.GlobalConfiguration.DownstreamHttpVersion);
|
||||
|
||||
return new InternalConfiguration(routes,
|
||||
adminPath,
|
||||
serviceProviderConfiguration,
|
||||
fileConfiguration.GlobalConfiguration.RequestIdKey,
|
||||
lbOptions,
|
||||
fileConfiguration.GlobalConfiguration.DownstreamScheme,
|
||||
qosOptions,
|
||||
httpHandlerOptions,
|
||||
version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class DownstreamAddressesCreator : IDownstreamAddressesCreator
|
||||
{
|
||||
public List<DownstreamHostAndPort> Create(FileReRoute reRoute)
|
||||
public List<DownstreamHostAndPort> Create(FileRoute route)
|
||||
{
|
||||
return reRoute.DownstreamHostAndPorts.Select(hostAndPort => new DownstreamHostAndPort(hostAndPort.Host, hostAndPort.Port)).ToList();
|
||||
return route.DownstreamHostAndPorts.Select(hostAndPort => new DownstreamHostAndPort(hostAndPort.Host, hostAndPort.Port)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,47 @@
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Builder;
|
||||
using File;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class DynamicsCreator : IDynamicsCreator
|
||||
{
|
||||
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||
private readonly IVersionCreator _versionCreator;
|
||||
|
||||
public DynamicsCreator(IRateLimitOptionsCreator rateLimitOptionsCreator, IVersionCreator versionCreator)
|
||||
{
|
||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||
_versionCreator = versionCreator;
|
||||
}
|
||||
|
||||
public List<ReRoute> Create(FileConfiguration fileConfiguration)
|
||||
{
|
||||
return fileConfiguration.DynamicReRoutes
|
||||
.Select(dynamic => SetUpDynamicReRoute(dynamic, fileConfiguration.GlobalConfiguration))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private ReRoute SetUpDynamicReRoute(FileDynamicReRoute fileDynamicReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var rateLimitOption = _rateLimitOptionsCreator
|
||||
.Create(fileDynamicReRoute.RateLimitRule, globalConfiguration);
|
||||
|
||||
var version = _versionCreator.Create(fileDynamicReRoute.DownstreamHttpVersion);
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(rateLimitOption.EnableRateLimiting)
|
||||
.WithRateLimitOptions(rateLimitOption)
|
||||
.WithServiceName(fileDynamicReRoute.ServiceName)
|
||||
.WithDownstreamHttpVersion(version)
|
||||
.Build();
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build();
|
||||
|
||||
return reRoute;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Builder;
|
||||
using File;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class DynamicsCreator : IDynamicsCreator
|
||||
{
|
||||
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||
private readonly IVersionCreator _versionCreator;
|
||||
|
||||
public DynamicsCreator(IRateLimitOptionsCreator rateLimitOptionsCreator, IVersionCreator versionCreator)
|
||||
{
|
||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||
_versionCreator = versionCreator;
|
||||
}
|
||||
|
||||
public List<Route> Create(FileConfiguration fileConfiguration)
|
||||
{
|
||||
return fileConfiguration.DynamicRoutes
|
||||
.Select(dynamic => SetUpDynamicRoute(dynamic, fileConfiguration.GlobalConfiguration))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private Route SetUpDynamicRoute(FileDynamicRoute fileDynamicRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var rateLimitOption = _rateLimitOptionsCreator
|
||||
.Create(fileDynamicRoute.RateLimitRule, globalConfiguration);
|
||||
|
||||
var version = _versionCreator.Create(fileDynamicRoute.DownstreamHttpVersion);
|
||||
|
||||
var downstreamRoute = new DownstreamRouteBuilder()
|
||||
.WithEnableRateLimiting(rateLimitOption.EnableRateLimiting)
|
||||
.WithRateLimitOptions(rateLimitOption)
|
||||
.WithServiceName(fileDynamicRoute.ServiceName)
|
||||
.WithDownstreamHttpVersion(version)
|
||||
.Build();
|
||||
|
||||
var route = new RouteBuilder()
|
||||
.WithDownstreamRoute(downstreamRoute)
|
||||
.Build();
|
||||
|
||||
return route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,57 @@
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using File;
|
||||
using Responses;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Validator;
|
||||
|
||||
public class FileInternalConfigurationCreator : IInternalConfigurationCreator
|
||||
{
|
||||
private readonly IConfigurationValidator _configurationValidator;
|
||||
private readonly IConfigurationCreator _configCreator;
|
||||
private readonly IDynamicsCreator _dynamicsCreator;
|
||||
private readonly IReRoutesCreator _reRoutesCreator;
|
||||
private readonly IAggregatesCreator _aggregatesCreator;
|
||||
|
||||
public FileInternalConfigurationCreator(
|
||||
IConfigurationValidator configurationValidator,
|
||||
IReRoutesCreator reRoutesCreator,
|
||||
IAggregatesCreator aggregatesCreator,
|
||||
IDynamicsCreator dynamicsCreator,
|
||||
IConfigurationCreator configCreator
|
||||
)
|
||||
{
|
||||
_configCreator = configCreator;
|
||||
_dynamicsCreator = dynamicsCreator;
|
||||
_aggregatesCreator = aggregatesCreator;
|
||||
_reRoutesCreator = reRoutesCreator;
|
||||
_configurationValidator = configurationValidator;
|
||||
}
|
||||
|
||||
public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
|
||||
{
|
||||
var response = await _configurationValidator.IsValid(fileConfiguration);
|
||||
|
||||
if (response.Data.IsError)
|
||||
{
|
||||
return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
|
||||
}
|
||||
|
||||
var reRoutes = _reRoutesCreator.Create(fileConfiguration);
|
||||
|
||||
var aggregates = _aggregatesCreator.Create(fileConfiguration, reRoutes);
|
||||
|
||||
var dynamicReRoute = _dynamicsCreator.Create(fileConfiguration);
|
||||
|
||||
var mergedReRoutes = reRoutes
|
||||
.Union(aggregates)
|
||||
.Union(dynamicReRoute)
|
||||
.ToList();
|
||||
|
||||
var config = _configCreator.Create(fileConfiguration, mergedReRoutes);
|
||||
|
||||
return new OkResponse<IInternalConfiguration>(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using File;
|
||||
using Responses;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Validator;
|
||||
|
||||
public class FileInternalConfigurationCreator : IInternalConfigurationCreator
|
||||
{
|
||||
private readonly IConfigurationValidator _configurationValidator;
|
||||
private readonly IConfigurationCreator _configCreator;
|
||||
private readonly IDynamicsCreator _dynamicsCreator;
|
||||
private readonly IRoutesCreator _routesCreator;
|
||||
private readonly IAggregatesCreator _aggregatesCreator;
|
||||
|
||||
public FileInternalConfigurationCreator(
|
||||
IConfigurationValidator configurationValidator,
|
||||
IRoutesCreator routesCreator,
|
||||
IAggregatesCreator aggregatesCreator,
|
||||
IDynamicsCreator dynamicsCreator,
|
||||
IConfigurationCreator configCreator
|
||||
)
|
||||
{
|
||||
_configCreator = configCreator;
|
||||
_dynamicsCreator = dynamicsCreator;
|
||||
_aggregatesCreator = aggregatesCreator;
|
||||
_routesCreator = routesCreator;
|
||||
_configurationValidator = configurationValidator;
|
||||
}
|
||||
|
||||
public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
|
||||
{
|
||||
var response = await _configurationValidator.IsValid(fileConfiguration);
|
||||
|
||||
if (response.Data.IsError)
|
||||
{
|
||||
return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
|
||||
}
|
||||
|
||||
var routes = _routesCreator.Create(fileConfiguration);
|
||||
|
||||
var aggregates = _aggregatesCreator.Create(fileConfiguration, routes);
|
||||
|
||||
var dynamicRoute = _dynamicsCreator.Create(fileConfiguration);
|
||||
|
||||
var mergedRoutes = routes
|
||||
.Union(aggregates)
|
||||
.Union(dynamicRoute)
|
||||
.ToList();
|
||||
|
||||
var config = _configCreator.Create(fileConfiguration, mergedRoutes);
|
||||
|
||||
return new OkResponse<IInternalConfiguration>(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ namespace Ocelot.Configuration.Creator
|
||||
_placeholders = placeholders;
|
||||
}
|
||||
|
||||
public HeaderTransformations Create(FileReRoute fileReRoute)
|
||||
public HeaderTransformations Create(FileRoute fileRoute)
|
||||
{
|
||||
var upstream = new List<HeaderFindAndReplace>();
|
||||
var addHeadersToUpstream = new List<AddHeader>();
|
||||
|
||||
foreach (var input in fileReRoute.UpstreamHeaderTransform)
|
||||
foreach (var input in fileRoute.UpstreamHeaderTransform)
|
||||
{
|
||||
if (input.Value.Contains(","))
|
||||
{
|
||||
@ -44,9 +44,9 @@ namespace Ocelot.Configuration.Creator
|
||||
}
|
||||
|
||||
var downstream = new List<HeaderFindAndReplace>();
|
||||
var addHeadersToDownstream = new List<AddHeader>();
|
||||
|
||||
foreach (var input in fileReRoute.DownstreamHeaderTransform)
|
||||
var addHeadersToDownstream = new List<AddHeader>();
|
||||
|
||||
foreach (var input in fileRoute.DownstreamHeaderTransform)
|
||||
{
|
||||
if (input.Value.Contains(","))
|
||||
{
|
||||
@ -64,8 +64,8 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
addHeadersToDownstream.Add(new AddHeader(input.Key, input.Value));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new HeaderTransformations(upstream, downstream, addHeadersToDownstream, addHeadersToUpstream);
|
||||
}
|
||||
|
||||
@ -78,8 +78,8 @@ namespace Ocelot.Configuration.Creator
|
||||
var startOfPlaceholder = replace.IndexOf("{");
|
||||
if (startOfPlaceholder > -1)
|
||||
{
|
||||
var endOfPlaceholder = replace.IndexOf("}", startOfPlaceholder);
|
||||
|
||||
var endOfPlaceholder = replace.IndexOf("}", startOfPlaceholder);
|
||||
|
||||
var placeholder = replace.Substring(startOfPlaceholder, startOfPlaceholder + (endOfPlaceholder + 1));
|
||||
|
||||
var value = _placeholders.Get(placeholder);
|
||||
@ -92,9 +92,9 @@ namespace Ocelot.Configuration.Creator
|
||||
replace = replace.Replace(placeholder, value.Data);
|
||||
}
|
||||
|
||||
var hAndr = new HeaderFindAndReplace(input.Key, findAndReplace[0], replace, 0);
|
||||
|
||||
var hAndr = new HeaderFindAndReplace(input.Key, findAndReplace[0], replace, 0);
|
||||
|
||||
return new OkResponse<HeaderFindAndReplace>(hAndr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IAggregatesCreator
|
||||
{
|
||||
List<ReRoute> Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes);
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IAggregatesCreator
|
||||
{
|
||||
List<Route> Create(FileConfiguration fileConfiguration, List<Route> routes);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IAuthenticationOptionsCreator
|
||||
{
|
||||
AuthenticationOptions Create(FileReRoute reRoute);
|
||||
AuthenticationOptions Create(FileRoute route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IConfigurationCreator
|
||||
{
|
||||
InternalConfiguration Create(FileConfiguration fileConfiguration, List<ReRoute> reRoutes);
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IConfigurationCreator
|
||||
{
|
||||
InternalConfiguration Create(FileConfiguration fileConfiguration, List<Route> routes);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,6 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IDownstreamAddressesCreator
|
||||
{
|
||||
List<DownstreamHostAndPort> Create(FileReRoute reRoute);
|
||||
List<DownstreamHostAndPort> Create(FileRoute route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IDynamicsCreator
|
||||
{
|
||||
List<ReRoute> Create(FileConfiguration fileConfiguration);
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IDynamicsCreator
|
||||
{
|
||||
List<Route> Create(FileConfiguration fileConfiguration);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IHeaderFindAndReplaceCreator
|
||||
{
|
||||
HeaderTransformations Create(FileReRoute fileReRoute);
|
||||
HeaderTransformations Create(FileRoute fileRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ namespace Ocelot.Configuration.Creator
|
||||
/// </summary>
|
||||
public interface IHttpHandlerOptionsCreator
|
||||
{
|
||||
HttpHandlerOptions Create(FileHttpHandlerOptions fileReRoute);
|
||||
HttpHandlerOptions Create(FileHttpHandlerOptions fileRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IReRouteKeyCreator
|
||||
{
|
||||
string Create(FileReRoute fileReRoute);
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IReRouteOptionsCreator
|
||||
{
|
||||
ReRouteOptions Create(FileReRoute fileReRoute);
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IReRoutesCreator
|
||||
{
|
||||
List<ReRoute> Create(FileConfiguration fileConfiguration);
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IRoutesCreator
|
||||
{
|
||||
List<Route> Create(FileConfiguration fileConfiguration);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IRequestIdKeyCreator
|
||||
{
|
||||
string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration);
|
||||
string Create(FileRoute fileRoute, FileGlobalConfiguration globalConfiguration);
|
||||
}
|
||||
}
|
9
src/Ocelot/Configuration/Creator/IRouteKeyCreator.cs
Normal file
9
src/Ocelot/Configuration/Creator/IRouteKeyCreator.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IRouteKeyCreator
|
||||
{
|
||||
string Create(FileRoute fileRoute);
|
||||
}
|
||||
}
|
9
src/Ocelot/Configuration/Creator/IRouteOptionsCreator.cs
Normal file
9
src/Ocelot/Configuration/Creator/IRouteOptionsCreator.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IRouteOptionsCreator
|
||||
{
|
||||
RouteOptions Create(FileRoute fileRoute);
|
||||
}
|
||||
}
|
@ -5,6 +5,6 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IUpstreamTemplatePatternCreator
|
||||
{
|
||||
UpstreamPathTemplate Create(IReRoute reRoute);
|
||||
UpstreamPathTemplate Create(IRoute route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class ReRouteKeyCreator : IReRouteKeyCreator
|
||||
{
|
||||
public string Create(FileReRoute fileReRoute)
|
||||
{
|
||||
if (IsStickySession(fileReRoute))
|
||||
{
|
||||
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
|
||||
}
|
||||
|
||||
return $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}|{string.Join(",", fileReRoute.DownstreamHostAndPorts.Select(x => $"{x.Host}:{x.Port}"))}";
|
||||
}
|
||||
|
||||
private bool IsStickySession(FileReRoute fileReRoute)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(fileReRoute.LoadBalancerOptions.Type)
|
||||
&& !string.IsNullOrEmpty(fileReRoute.LoadBalancerOptions.Key)
|
||||
&& fileReRoute.LoadBalancerOptions.Type == nameof(CookieStickySessions))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class ReRouteOptionsCreator : IReRouteOptionsCreator
|
||||
{
|
||||
public ReRouteOptions Create(FileReRoute fileReRoute)
|
||||
{
|
||||
var isAuthenticated = IsAuthenticated(fileReRoute);
|
||||
var isAuthorised = IsAuthorised(fileReRoute);
|
||||
var isCached = IsCached(fileReRoute);
|
||||
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
|
||||
var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName);
|
||||
|
||||
var options = new ReRouteOptionsBuilder()
|
||||
.WithIsAuthenticated(isAuthenticated)
|
||||
.WithIsAuthorised(isAuthorised)
|
||||
.WithIsCached(isCached)
|
||||
.WithRateLimiting(enableRateLimiting)
|
||||
.WithUseServiceDiscovery(useServiceDiscovery)
|
||||
.Build();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static bool IsEnableRateLimiting(FileReRoute fileReRoute)
|
||||
{
|
||||
return (fileReRoute.RateLimitOptions != null && fileReRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
|
||||
}
|
||||
|
||||
private bool IsAuthenticated(FileReRoute fileReRoute)
|
||||
{
|
||||
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.AuthenticationProviderKey);
|
||||
}
|
||||
|
||||
private bool IsAuthorised(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.RouteClaimsRequirement?.Count > 0;
|
||||
}
|
||||
|
||||
private bool IsCached(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.FileCacheOptions.TtlSeconds > 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,15 +4,15 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class RequestIdKeyCreator : IRequestIdKeyCreator
|
||||
{
|
||||
public string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
public string Create(FileRoute fileRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var reRouteId = !string.IsNullOrEmpty(fileReRoute.RequestIdKey);
|
||||
|
||||
var requestIdKey = reRouteId
|
||||
? fileReRoute.RequestIdKey
|
||||
: globalConfiguration.RequestIdKey;
|
||||
|
||||
var routeId = !string.IsNullOrEmpty(fileRoute.RequestIdKey);
|
||||
|
||||
var requestIdKey = routeId
|
||||
? fileRoute.RequestIdKey
|
||||
: globalConfiguration.RequestIdKey;
|
||||
|
||||
return requestIdKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
31
src/Ocelot/Configuration/Creator/RouteKeyCreator.cs
Normal file
31
src/Ocelot/Configuration/Creator/RouteKeyCreator.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class RouteKeyCreator : IRouteKeyCreator
|
||||
{
|
||||
public string Create(FileRoute fileRoute)
|
||||
{
|
||||
if (IsStickySession(fileRoute))
|
||||
{
|
||||
return $"{nameof(CookieStickySessions)}:{fileRoute.LoadBalancerOptions.Key}";
|
||||
}
|
||||
|
||||
return $"{fileRoute.UpstreamPathTemplate}|{string.Join(",", fileRoute.UpstreamHttpMethod)}|{string.Join(",", fileRoute.DownstreamHostAndPorts.Select(x => $"{x.Host}:{x.Port}"))}";
|
||||
}
|
||||
|
||||
private bool IsStickySession(FileRoute fileRoute)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(fileRoute.LoadBalancerOptions.Type)
|
||||
&& !string.IsNullOrEmpty(fileRoute.LoadBalancerOptions.Key)
|
||||
&& fileRoute.LoadBalancerOptions.Type == nameof(CookieStickySessions))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
47
src/Ocelot/Configuration/Creator/RouteOptionsCreator.cs
Normal file
47
src/Ocelot/Configuration/Creator/RouteOptionsCreator.cs
Normal file
@ -0,0 +1,47 @@
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
public class RouteOptionsCreator : IRouteOptionsCreator
|
||||
{
|
||||
public RouteOptions Create(FileRoute fileRoute)
|
||||
{
|
||||
var isAuthenticated = IsAuthenticated(fileRoute);
|
||||
var isAuthorised = IsAuthorised(fileRoute);
|
||||
var isCached = IsCached(fileRoute);
|
||||
var enableRateLimiting = IsEnableRateLimiting(fileRoute);
|
||||
var useServiceDiscovery = !string.IsNullOrEmpty(fileRoute.ServiceName);
|
||||
|
||||
var options = new RouteOptionsBuilder()
|
||||
.WithIsAuthenticated(isAuthenticated)
|
||||
.WithIsAuthorised(isAuthorised)
|
||||
.WithIsCached(isCached)
|
||||
.WithRateLimiting(enableRateLimiting)
|
||||
.WithUseServiceDiscovery(useServiceDiscovery)
|
||||
.Build();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static bool IsEnableRateLimiting(FileRoute fileRoute)
|
||||
{
|
||||
return (fileRoute.RateLimitOptions != null && fileRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
|
||||
}
|
||||
|
||||
private bool IsAuthenticated(FileRoute fileRoute)
|
||||
{
|
||||
return !string.IsNullOrEmpty(fileRoute.AuthenticationOptions?.AuthenticationProviderKey);
|
||||
}
|
||||
|
||||
private bool IsAuthorised(FileRoute fileRoute)
|
||||
{
|
||||
return fileRoute.RouteClaimsRequirement?.Count > 0;
|
||||
}
|
||||
|
||||
private bool IsCached(FileRoute fileRoute)
|
||||
{
|
||||
return fileRoute.FileCacheOptions.TtlSeconds > 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,167 +1,167 @@
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Builder;
|
||||
using Cache;
|
||||
using File;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class ReRoutesCreator : IReRoutesCreator
|
||||
{
|
||||
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
|
||||
private readonly IClaimsToThingCreator _claimsToThingCreator;
|
||||
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
|
||||
private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
|
||||
private readonly IRequestIdKeyCreator _requestIdKeyCreator;
|
||||
private readonly IQoSOptionsCreator _qosOptionsCreator;
|
||||
private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
|
||||
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||
private readonly IRegionCreator _regionCreator;
|
||||
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
|
||||
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
|
||||
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
|
||||
private readonly IReRouteKeyCreator _reRouteKeyCreator;
|
||||
private readonly ISecurityOptionsCreator _securityOptionsCreator;
|
||||
private readonly IVersionCreator _versionCreator;
|
||||
|
||||
public ReRoutesCreator(
|
||||
IClaimsToThingCreator claimsToThingCreator,
|
||||
IAuthenticationOptionsCreator authOptionsCreator,
|
||||
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
|
||||
IRequestIdKeyCreator requestIdKeyCreator,
|
||||
IQoSOptionsCreator qosOptionsCreator,
|
||||
IReRouteOptionsCreator fileReRouteOptionsCreator,
|
||||
IRateLimitOptionsCreator rateLimitOptionsCreator,
|
||||
IRegionCreator regionCreator,
|
||||
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
|
||||
IHeaderFindAndReplaceCreator headerFAndRCreator,
|
||||
IDownstreamAddressesCreator downstreamAddressesCreator,
|
||||
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
|
||||
IReRouteKeyCreator reRouteKeyCreator,
|
||||
ISecurityOptionsCreator securityOptionsCreator,
|
||||
IVersionCreator versionCreator
|
||||
)
|
||||
{
|
||||
_reRouteKeyCreator = reRouteKeyCreator;
|
||||
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
|
||||
_downstreamAddressesCreator = downstreamAddressesCreator;
|
||||
_headerFAndRCreator = headerFAndRCreator;
|
||||
_regionCreator = regionCreator;
|
||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||
_requestIdKeyCreator = requestIdKeyCreator;
|
||||
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
||||
_authOptionsCreator = authOptionsCreator;
|
||||
_claimsToThingCreator = claimsToThingCreator;
|
||||
_qosOptionsCreator = qosOptionsCreator;
|
||||
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
|
||||
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
|
||||
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
|
||||
_securityOptionsCreator = securityOptionsCreator;
|
||||
_versionCreator = versionCreator;
|
||||
}
|
||||
|
||||
public List<ReRoute> Create(FileConfiguration fileConfiguration)
|
||||
{
|
||||
return fileConfiguration.ReRoutes
|
||||
.Select(reRoute =>
|
||||
{
|
||||
var downstreamReRoute = SetUpDownstreamReRoute(reRoute, fileConfiguration.GlobalConfiguration);
|
||||
return SetUpReRoute(reRoute, downstreamReRoute);
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute);
|
||||
|
||||
var requestIdKey = _requestIdKeyCreator.Create(fileReRoute, globalConfiguration);
|
||||
|
||||
var reRouteKey = _reRouteKeyCreator.Create(fileReRoute);
|
||||
|
||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
||||
|
||||
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
|
||||
|
||||
var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
|
||||
|
||||
var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
|
||||
|
||||
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
|
||||
|
||||
var claimsToDownstreamPath = _claimsToThingCreator.Create(fileReRoute.ChangeDownstreamPathTemplate);
|
||||
|
||||
var qosOptions = _qosOptionsCreator.Create(fileReRoute.QoSOptions, fileReRoute.UpstreamPathTemplate, fileReRoute.UpstreamHttpMethod);
|
||||
|
||||
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute.RateLimitOptions, globalConfiguration);
|
||||
|
||||
var region = _regionCreator.Create(fileReRoute);
|
||||
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute.HttpHandlerOptions);
|
||||
|
||||
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
|
||||
|
||||
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
|
||||
|
||||
var lbOptions = _loadBalancerOptionsCreator.Create(fileReRoute.LoadBalancerOptions);
|
||||
|
||||
var securityOptions = _securityOptionsCreator.Create(fileReRoute.SecurityOptions);
|
||||
|
||||
var downstreamHttpVersion = _versionCreator.Create(fileReRoute.DownstreamHttpVersion);
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithKey(fileReRoute.Key)
|
||||
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
|
||||
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamPathTemplate(upstreamTemplatePattern)
|
||||
.WithIsAuthenticated(fileReRouteOptions.IsAuthenticated)
|
||||
.WithAuthenticationOptions(authOptionsForRoute)
|
||||
.WithClaimsToHeaders(claimsToHeaders)
|
||||
.WithClaimsToClaims(claimsToClaims)
|
||||
.WithRouteClaimsRequirement(fileReRoute.RouteClaimsRequirement)
|
||||
.WithIsAuthorised(fileReRouteOptions.IsAuthorised)
|
||||
.WithClaimsToQueries(claimsToQueries)
|
||||
.WithClaimsToDownstreamPath(claimsToDownstreamPath)
|
||||
.WithRequestIdKey(requestIdKey)
|
||||
.WithIsCached(fileReRouteOptions.IsCached)
|
||||
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
|
||||
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
||||
.WithLoadBalancerOptions(lbOptions)
|
||||
.WithDownstreamAddresses(downstreamAddresses)
|
||||
.WithLoadBalancerKey(reRouteKey)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
|
||||
.WithRateLimitOptions(rateLimitOption)
|
||||
.WithHttpHandlerOptions(httpHandlerOptions)
|
||||
.WithServiceName(fileReRoute.ServiceName)
|
||||
.WithServiceNamespace(fileReRoute.ServiceNamespace)
|
||||
.WithUseServiceDiscovery(fileReRouteOptions.UseServiceDiscovery)
|
||||
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
|
||||
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
|
||||
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
|
||||
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
|
||||
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
|
||||
.WithDangerousAcceptAnyServerCertificateValidator(fileReRoute.DangerousAcceptAnyServerCertificateValidator)
|
||||
.WithSecurityOptions(securityOptions)
|
||||
.WithDownstreamHttpVersion(downstreamHttpVersion)
|
||||
.WithDownStreamHttpMethod(fileReRoute.DownstreamHttpMethod)
|
||||
.Build();
|
||||
|
||||
return reRoute;
|
||||
}
|
||||
|
||||
private ReRoute SetUpReRoute(FileReRoute fileReRoute, DownstreamReRoute downstreamReRoutes)
|
||||
{
|
||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamPathTemplate(upstreamTemplatePattern)
|
||||
.WithDownstreamReRoute(downstreamReRoutes)
|
||||
.WithUpstreamHost(fileReRoute.UpstreamHost)
|
||||
.Build();
|
||||
|
||||
return reRoute;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class RoutesCreator : IRoutesCreator
|
||||
{
|
||||
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
|
||||
private readonly IClaimsToThingCreator _claimsToThingCreator;
|
||||
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
|
||||
private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
|
||||
private readonly IRequestIdKeyCreator _requestIdKeyCreator;
|
||||
private readonly IQoSOptionsCreator _qosOptionsCreator;
|
||||
private readonly IRouteOptionsCreator _fileRouteOptionsCreator;
|
||||
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||
private readonly IRegionCreator _regionCreator;
|
||||
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
|
||||
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
|
||||
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
|
||||
private readonly IRouteKeyCreator _routeKeyCreator;
|
||||
private readonly ISecurityOptionsCreator _securityOptionsCreator;
|
||||
private readonly IVersionCreator _versionCreator;
|
||||
|
||||
public RoutesCreator(
|
||||
IClaimsToThingCreator claimsToThingCreator,
|
||||
IAuthenticationOptionsCreator authOptionsCreator,
|
||||
IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
|
||||
IRequestIdKeyCreator requestIdKeyCreator,
|
||||
IQoSOptionsCreator qosOptionsCreator,
|
||||
IRouteOptionsCreator fileRouteOptionsCreator,
|
||||
IRateLimitOptionsCreator rateLimitOptionsCreator,
|
||||
IRegionCreator regionCreator,
|
||||
IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
|
||||
IHeaderFindAndReplaceCreator headerFAndRCreator,
|
||||
IDownstreamAddressesCreator downstreamAddressesCreator,
|
||||
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
|
||||
IRouteKeyCreator routeKeyCreator,
|
||||
ISecurityOptionsCreator securityOptionsCreator,
|
||||
IVersionCreator versionCreator
|
||||
)
|
||||
{
|
||||
_routeKeyCreator = routeKeyCreator;
|
||||
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
|
||||
_downstreamAddressesCreator = downstreamAddressesCreator;
|
||||
_headerFAndRCreator = headerFAndRCreator;
|
||||
_regionCreator = regionCreator;
|
||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||
_requestIdKeyCreator = requestIdKeyCreator;
|
||||
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
||||
_authOptionsCreator = authOptionsCreator;
|
||||
_claimsToThingCreator = claimsToThingCreator;
|
||||
_qosOptionsCreator = qosOptionsCreator;
|
||||
_fileRouteOptionsCreator = fileRouteOptionsCreator;
|
||||
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
|
||||
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
|
||||
_securityOptionsCreator = securityOptionsCreator;
|
||||
_versionCreator = versionCreator;
|
||||
}
|
||||
|
||||
public List<Route> Create(FileConfiguration fileConfiguration)
|
||||
{
|
||||
return fileConfiguration.Routes
|
||||
.Select(route =>
|
||||
{
|
||||
var downstreamRoute = SetUpDownstreamRoute(route, fileConfiguration.GlobalConfiguration);
|
||||
return SetUpRoute(route, downstreamRoute);
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private DownstreamRoute SetUpDownstreamRoute(FileRoute fileRoute, FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
var fileRouteOptions = _fileRouteOptionsCreator.Create(fileRoute);
|
||||
|
||||
var requestIdKey = _requestIdKeyCreator.Create(fileRoute, globalConfiguration);
|
||||
|
||||
var routeKey = _routeKeyCreator.Create(fileRoute);
|
||||
|
||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileRoute);
|
||||
|
||||
var authOptionsForRoute = _authOptionsCreator.Create(fileRoute);
|
||||
|
||||
var claimsToHeaders = _claimsToThingCreator.Create(fileRoute.AddHeadersToRequest);
|
||||
|
||||
var claimsToClaims = _claimsToThingCreator.Create(fileRoute.AddClaimsToRequest);
|
||||
|
||||
var claimsToQueries = _claimsToThingCreator.Create(fileRoute.AddQueriesToRequest);
|
||||
|
||||
var claimsToDownstreamPath = _claimsToThingCreator.Create(fileRoute.ChangeDownstreamPathTemplate);
|
||||
|
||||
var qosOptions = _qosOptionsCreator.Create(fileRoute.QoSOptions, fileRoute.UpstreamPathTemplate, fileRoute.UpstreamHttpMethod);
|
||||
|
||||
var rateLimitOption = _rateLimitOptionsCreator.Create(fileRoute.RateLimitOptions, globalConfiguration);
|
||||
|
||||
var region = _regionCreator.Create(fileRoute);
|
||||
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileRoute.HttpHandlerOptions);
|
||||
|
||||
var hAndRs = _headerFAndRCreator.Create(fileRoute);
|
||||
|
||||
var downstreamAddresses = _downstreamAddressesCreator.Create(fileRoute);
|
||||
|
||||
var lbOptions = _loadBalancerOptionsCreator.Create(fileRoute.LoadBalancerOptions);
|
||||
|
||||
var securityOptions = _securityOptionsCreator.Create(fileRoute.SecurityOptions);
|
||||
|
||||
var downstreamHttpVersion = _versionCreator.Create(fileRoute.DownstreamHttpVersion);
|
||||
|
||||
var route = new DownstreamRouteBuilder()
|
||||
.WithKey(fileRoute.Key)
|
||||
.WithDownstreamPathTemplate(fileRoute.DownstreamPathTemplate)
|
||||
.WithUpstreamHttpMethod(fileRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamPathTemplate(upstreamTemplatePattern)
|
||||
.WithIsAuthenticated(fileRouteOptions.IsAuthenticated)
|
||||
.WithAuthenticationOptions(authOptionsForRoute)
|
||||
.WithClaimsToHeaders(claimsToHeaders)
|
||||
.WithClaimsToClaims(claimsToClaims)
|
||||
.WithRouteClaimsRequirement(fileRoute.RouteClaimsRequirement)
|
||||
.WithIsAuthorised(fileRouteOptions.IsAuthorised)
|
||||
.WithClaimsToQueries(claimsToQueries)
|
||||
.WithClaimsToDownstreamPath(claimsToDownstreamPath)
|
||||
.WithRequestIdKey(requestIdKey)
|
||||
.WithIsCached(fileRouteOptions.IsCached)
|
||||
.WithCacheOptions(new CacheOptions(fileRoute.FileCacheOptions.TtlSeconds, region))
|
||||
.WithDownstreamScheme(fileRoute.DownstreamScheme)
|
||||
.WithLoadBalancerOptions(lbOptions)
|
||||
.WithDownstreamAddresses(downstreamAddresses)
|
||||
.WithLoadBalancerKey(routeKey)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithEnableRateLimiting(fileRouteOptions.EnableRateLimiting)
|
||||
.WithRateLimitOptions(rateLimitOption)
|
||||
.WithHttpHandlerOptions(httpHandlerOptions)
|
||||
.WithServiceName(fileRoute.ServiceName)
|
||||
.WithServiceNamespace(fileRoute.ServiceNamespace)
|
||||
.WithUseServiceDiscovery(fileRouteOptions.UseServiceDiscovery)
|
||||
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
|
||||
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
|
||||
.WithDelegatingHandlers(fileRoute.DelegatingHandlers)
|
||||
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
|
||||
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
|
||||
.WithDangerousAcceptAnyServerCertificateValidator(fileRoute.DangerousAcceptAnyServerCertificateValidator)
|
||||
.WithSecurityOptions(securityOptions)
|
||||
.WithDownstreamHttpVersion(downstreamHttpVersion)
|
||||
.WithDownStreamHttpMethod(fileRoute.DownstreamHttpMethod)
|
||||
.Build();
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
private Route SetUpRoute(FileRoute fileRoute, DownstreamRoute downstreamRoutes)
|
||||
{
|
||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileRoute);
|
||||
|
||||
var route = new RouteBuilder()
|
||||
.WithUpstreamHttpMethod(fileRoute.UpstreamHttpMethod)
|
||||
.WithUpstreamPathTemplate(upstreamTemplatePattern)
|
||||
.WithDownstreamRoute(downstreamRoutes)
|
||||
.WithUpstreamHost(fileRoute.UpstreamHost)
|
||||
.Build();
|
||||
|
||||
return route;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,93 +1,93 @@
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Values;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator
|
||||
{
|
||||
private const string RegExMatchOneOrMoreOfEverything = ".+";
|
||||
private const string RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash = "[^/]+";
|
||||
private const string RegExMatchEndString = "$";
|
||||
private const string RegExIgnoreCase = "(?i)";
|
||||
private const string RegExForwardSlashOnly = "^/$";
|
||||
private const string RegExForwardSlashAndOnePlaceHolder = "^/.*";
|
||||
|
||||
public UpstreamPathTemplate Create(IReRoute reRoute)
|
||||
{
|
||||
var upstreamTemplate = reRoute.UpstreamPathTemplate;
|
||||
|
||||
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 placeHolderName = upstreamTemplate.Substring(i, difference);
|
||||
placeholders.Add(placeHolderName);
|
||||
|
||||
//hack to handle /{url} case
|
||||
if (ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
|
||||
{
|
||||
return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0, false, reRoute.UpstreamPathTemplate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var containsQueryString = false;
|
||||
|
||||
if (upstreamTemplate.Contains("?"))
|
||||
{
|
||||
containsQueryString = true;
|
||||
upstreamTemplate = upstreamTemplate.Replace("?", "\\?");
|
||||
}
|
||||
|
||||
for (int i = 0; i < placeholders.Count; i++)
|
||||
{
|
||||
var indexOfPlaceholder = upstreamTemplate.IndexOf(placeholders[i]);
|
||||
var indexOfNextForwardSlash = upstreamTemplate.IndexOf("/", indexOfPlaceholder);
|
||||
if (indexOfNextForwardSlash < indexOfPlaceholder || (containsQueryString && upstreamTemplate.IndexOf("?") < upstreamTemplate.IndexOf(placeholders[i])))
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverything);
|
||||
}
|
||||
else
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash);
|
||||
}
|
||||
}
|
||||
|
||||
if (upstreamTemplate == "/")
|
||||
{
|
||||
return new UpstreamPathTemplate(RegExForwardSlashOnly, reRoute.Priority, containsQueryString, reRoute.UpstreamPathTemplate);
|
||||
}
|
||||
|
||||
if (upstreamTemplate.EndsWith("/"))
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Remove(upstreamTemplate.Length - 1, 1) + "(/|)";
|
||||
}
|
||||
|
||||
var route = reRoute.ReRouteIsCaseSensitive
|
||||
? $"^{upstreamTemplate}{RegExMatchEndString}"
|
||||
: $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
|
||||
|
||||
return new UpstreamPathTemplate(route, reRoute.Priority, containsQueryString, reRoute.UpstreamPathTemplate);
|
||||
}
|
||||
|
||||
private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
|
||||
{
|
||||
if (upstreamTemplate.Substring(0, 2) == "/{" && placeholders.Count == 1 && upstreamTemplate.Length == postitionOfPlaceHolderClosingBracket + 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||
{
|
||||
return upstreamTemplate[i] == '{';
|
||||
}
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Values;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator
|
||||
{
|
||||
private const string RegExMatchOneOrMoreOfEverything = ".+";
|
||||
private const string RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash = "[^/]+";
|
||||
private const string RegExMatchEndString = "$";
|
||||
private const string RegExIgnoreCase = "(?i)";
|
||||
private const string RegExForwardSlashOnly = "^/$";
|
||||
private const string RegExForwardSlashAndOnePlaceHolder = "^/.*";
|
||||
|
||||
public UpstreamPathTemplate Create(IRoute route)
|
||||
{
|
||||
var upstreamTemplate = route.UpstreamPathTemplate;
|
||||
|
||||
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 placeHolderName = upstreamTemplate.Substring(i, difference);
|
||||
placeholders.Add(placeHolderName);
|
||||
|
||||
//hack to handle /{url} case
|
||||
if (ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
|
||||
{
|
||||
return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0, false, route.UpstreamPathTemplate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var containsQueryString = false;
|
||||
|
||||
if (upstreamTemplate.Contains("?"))
|
||||
{
|
||||
containsQueryString = true;
|
||||
upstreamTemplate = upstreamTemplate.Replace("?", "\\?");
|
||||
}
|
||||
|
||||
for (int i = 0; i < placeholders.Count; i++)
|
||||
{
|
||||
var indexOfPlaceholder = upstreamTemplate.IndexOf(placeholders[i]);
|
||||
var indexOfNextForwardSlash = upstreamTemplate.IndexOf("/", indexOfPlaceholder);
|
||||
if (indexOfNextForwardSlash < indexOfPlaceholder || (containsQueryString && upstreamTemplate.IndexOf("?") < upstreamTemplate.IndexOf(placeholders[i])))
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverything);
|
||||
}
|
||||
else
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash);
|
||||
}
|
||||
}
|
||||
|
||||
if (upstreamTemplate == "/")
|
||||
{
|
||||
return new UpstreamPathTemplate(RegExForwardSlashOnly, route.Priority, containsQueryString, route.UpstreamPathTemplate);
|
||||
}
|
||||
|
||||
if (upstreamTemplate.EndsWith("/"))
|
||||
{
|
||||
upstreamTemplate = upstreamTemplate.Remove(upstreamTemplate.Length - 1, 1) + "(/|)";
|
||||
}
|
||||
|
||||
var template = route.RouteIsCaseSensitive
|
||||
? $"^{upstreamTemplate}{RegExMatchEndString}"
|
||||
: $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
|
||||
|
||||
return new UpstreamPathTemplate(template, route.Priority, containsQueryString, route.UpstreamPathTemplate);
|
||||
}
|
||||
|
||||
private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
|
||||
{
|
||||
if (upstreamTemplate.Substring(0, 2) == "/{" && placeholders.Count == 1 && upstreamTemplate.Length == postitionOfPlaceHolderClosingBracket + 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||
{
|
||||
return upstreamTemplate[i] == '{';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,117 +1,117 @@
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
using Creator;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Values;
|
||||
|
||||
public class DownstreamReRoute
|
||||
{
|
||||
public DownstreamReRoute(
|
||||
string key,
|
||||
UpstreamPathTemplate upstreamPathTemplate,
|
||||
List<HeaderFindAndReplace> upstreamHeadersFindAndReplace,
|
||||
List<HeaderFindAndReplace> downstreamHeadersFindAndReplace,
|
||||
List<DownstreamHostAndPort> downstreamAddresses,
|
||||
string serviceName,
|
||||
string serviceNamespace,
|
||||
HttpHandlerOptions httpHandlerOptions,
|
||||
bool useServiceDiscovery,
|
||||
bool enableEndpointEndpointRateLimiting,
|
||||
QoSOptions qosOptions,
|
||||
string downstreamScheme,
|
||||
string requestIdKey,
|
||||
bool isCached,
|
||||
CacheOptions cacheOptions,
|
||||
LoadBalancerOptions loadBalancerOptions,
|
||||
RateLimitOptions rateLimitOptions,
|
||||
Dictionary<string, string> routeClaimsRequirement,
|
||||
List<ClaimToThing> claimsToQueries,
|
||||
List<ClaimToThing> claimsToHeaders,
|
||||
List<ClaimToThing> claimsToClaims,
|
||||
List<ClaimToThing> claimsToPath,
|
||||
bool isAuthenticated,
|
||||
bool isAuthorised,
|
||||
AuthenticationOptions authenticationOptions,
|
||||
DownstreamPathTemplate downstreamPathTemplate,
|
||||
string loadBalancerKey,
|
||||
List<string> delegatingHandlers,
|
||||
List<AddHeader> addHeadersToDownstream,
|
||||
List<AddHeader> addHeadersToUpstream,
|
||||
bool dangerousAcceptAnyServerCertificateValidator,
|
||||
SecurityOptions securityOptions,
|
||||
string downstreamHttpMethod,
|
||||
Version downstreamHttpVersion)
|
||||
{
|
||||
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||
AddHeadersToDownstream = addHeadersToDownstream;
|
||||
DelegatingHandlers = delegatingHandlers;
|
||||
Key = key;
|
||||
UpstreamPathTemplate = upstreamPathTemplate;
|
||||
UpstreamHeadersFindAndReplace = upstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
||||
DownstreamHeadersFindAndReplace = downstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
||||
DownstreamAddresses = downstreamAddresses ?? new List<DownstreamHostAndPort>();
|
||||
ServiceName = serviceName;
|
||||
ServiceNamespace = serviceNamespace;
|
||||
HttpHandlerOptions = httpHandlerOptions;
|
||||
UseServiceDiscovery = useServiceDiscovery;
|
||||
EnableEndpointEndpointRateLimiting = enableEndpointEndpointRateLimiting;
|
||||
QosOptions = qosOptions;
|
||||
DownstreamScheme = downstreamScheme;
|
||||
RequestIdKey = requestIdKey;
|
||||
IsCached = isCached;
|
||||
CacheOptions = cacheOptions;
|
||||
LoadBalancerOptions = loadBalancerOptions;
|
||||
RateLimitOptions = rateLimitOptions;
|
||||
RouteClaimsRequirement = routeClaimsRequirement;
|
||||
ClaimsToQueries = claimsToQueries ?? new List<ClaimToThing>();
|
||||
ClaimsToHeaders = claimsToHeaders ?? new List<ClaimToThing>();
|
||||
ClaimsToClaims = claimsToClaims ?? new List<ClaimToThing>();
|
||||
ClaimsToPath = claimsToPath ?? new List<ClaimToThing>();
|
||||
IsAuthenticated = isAuthenticated;
|
||||
IsAuthorised = isAuthorised;
|
||||
AuthenticationOptions = authenticationOptions;
|
||||
DownstreamPathTemplate = downstreamPathTemplate;
|
||||
LoadBalancerKey = loadBalancerKey;
|
||||
AddHeadersToUpstream = addHeadersToUpstream;
|
||||
SecurityOptions = securityOptions;
|
||||
DownstreamHttpMethod = downstreamHttpMethod;
|
||||
DownstreamHttpVersion = downstreamHttpVersion;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public UpstreamPathTemplate UpstreamPathTemplate { get; }
|
||||
public List<HeaderFindAndReplace> UpstreamHeadersFindAndReplace { get; }
|
||||
public List<HeaderFindAndReplace> DownstreamHeadersFindAndReplace { get; }
|
||||
public List<DownstreamHostAndPort> DownstreamAddresses { get; }
|
||||
public string ServiceName { get; }
|
||||
public string ServiceNamespace { get; }
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
public bool UseServiceDiscovery { get; }
|
||||
public bool EnableEndpointEndpointRateLimiting { get; }
|
||||
public QoSOptions QosOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public string RequestIdKey { get; }
|
||||
public bool IsCached { get; }
|
||||
public CacheOptions CacheOptions { get; }
|
||||
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
public RateLimitOptions RateLimitOptions { get; }
|
||||
public Dictionary<string, string> RouteClaimsRequirement { get; }
|
||||
public List<ClaimToThing> ClaimsToQueries { get; }
|
||||
public List<ClaimToThing> ClaimsToHeaders { get; }
|
||||
public List<ClaimToThing> ClaimsToClaims { get; }
|
||||
public List<ClaimToThing> ClaimsToPath { get; }
|
||||
public bool IsAuthenticated { get; }
|
||||
public bool IsAuthorised { get; }
|
||||
public AuthenticationOptions AuthenticationOptions { get; }
|
||||
public DownstreamPathTemplate DownstreamPathTemplate { get; }
|
||||
public string LoadBalancerKey { get; }
|
||||
public List<string> DelegatingHandlers { get; }
|
||||
public List<AddHeader> AddHeadersToDownstream { get; }
|
||||
public List<AddHeader> AddHeadersToUpstream { get; }
|
||||
public bool DangerousAcceptAnyServerCertificateValidator { get; }
|
||||
public SecurityOptions SecurityOptions { get; }
|
||||
public string DownstreamHttpMethod { get; }
|
||||
public Version DownstreamHttpVersion { get; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
using Ocelot.Configuration.Creator;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Ocelot.Values;
|
||||
|
||||
public class DownstreamRoute
|
||||
{
|
||||
public DownstreamRoute(
|
||||
string key,
|
||||
UpstreamPathTemplate upstreamPathTemplate,
|
||||
List<HeaderFindAndReplace> upstreamHeadersFindAndReplace,
|
||||
List<HeaderFindAndReplace> downstreamHeadersFindAndReplace,
|
||||
List<DownstreamHostAndPort> downstreamAddresses,
|
||||
string serviceName,
|
||||
string serviceNamespace,
|
||||
HttpHandlerOptions httpHandlerOptions,
|
||||
bool useServiceDiscovery,
|
||||
bool enableEndpointEndpointRateLimiting,
|
||||
QoSOptions qosOptions,
|
||||
string downstreamScheme,
|
||||
string requestIdKey,
|
||||
bool isCached,
|
||||
CacheOptions cacheOptions,
|
||||
LoadBalancerOptions loadBalancerOptions,
|
||||
RateLimitOptions rateLimitOptions,
|
||||
Dictionary<string, string> routeClaimsRequirement,
|
||||
List<ClaimToThing> claimsToQueries,
|
||||
List<ClaimToThing> claimsToHeaders,
|
||||
List<ClaimToThing> claimsToClaims,
|
||||
List<ClaimToThing> claimsToPath,
|
||||
bool isAuthenticated,
|
||||
bool isAuthorised,
|
||||
AuthenticationOptions authenticationOptions,
|
||||
DownstreamPathTemplate downstreamPathTemplate,
|
||||
string loadBalancerKey,
|
||||
List<string> delegatingHandlers,
|
||||
List<AddHeader> addHeadersToDownstream,
|
||||
List<AddHeader> addHeadersToUpstream,
|
||||
bool dangerousAcceptAnyServerCertificateValidator,
|
||||
SecurityOptions securityOptions,
|
||||
string downstreamHttpMethod,
|
||||
Version downstreamHttpVersion)
|
||||
{
|
||||
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||
AddHeadersToDownstream = addHeadersToDownstream;
|
||||
DelegatingHandlers = delegatingHandlers;
|
||||
Key = key;
|
||||
UpstreamPathTemplate = upstreamPathTemplate;
|
||||
UpstreamHeadersFindAndReplace = upstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
||||
DownstreamHeadersFindAndReplace = downstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
||||
DownstreamAddresses = downstreamAddresses ?? new List<DownstreamHostAndPort>();
|
||||
ServiceName = serviceName;
|
||||
ServiceNamespace = serviceNamespace;
|
||||
HttpHandlerOptions = httpHandlerOptions;
|
||||
UseServiceDiscovery = useServiceDiscovery;
|
||||
EnableEndpointEndpointRateLimiting = enableEndpointEndpointRateLimiting;
|
||||
QosOptions = qosOptions;
|
||||
DownstreamScheme = downstreamScheme;
|
||||
RequestIdKey = requestIdKey;
|
||||
IsCached = isCached;
|
||||
CacheOptions = cacheOptions;
|
||||
LoadBalancerOptions = loadBalancerOptions;
|
||||
RateLimitOptions = rateLimitOptions;
|
||||
RouteClaimsRequirement = routeClaimsRequirement;
|
||||
ClaimsToQueries = claimsToQueries ?? new List<ClaimToThing>();
|
||||
ClaimsToHeaders = claimsToHeaders ?? new List<ClaimToThing>();
|
||||
ClaimsToClaims = claimsToClaims ?? new List<ClaimToThing>();
|
||||
ClaimsToPath = claimsToPath ?? new List<ClaimToThing>();
|
||||
IsAuthenticated = isAuthenticated;
|
||||
IsAuthorised = isAuthorised;
|
||||
AuthenticationOptions = authenticationOptions;
|
||||
DownstreamPathTemplate = downstreamPathTemplate;
|
||||
LoadBalancerKey = loadBalancerKey;
|
||||
AddHeadersToUpstream = addHeadersToUpstream;
|
||||
SecurityOptions = securityOptions;
|
||||
DownstreamHttpMethod = downstreamHttpMethod;
|
||||
DownstreamHttpVersion = downstreamHttpVersion;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public UpstreamPathTemplate UpstreamPathTemplate { get; }
|
||||
public List<HeaderFindAndReplace> UpstreamHeadersFindAndReplace { get; }
|
||||
public List<HeaderFindAndReplace> DownstreamHeadersFindAndReplace { get; }
|
||||
public List<DownstreamHostAndPort> DownstreamAddresses { get; }
|
||||
public string ServiceName { get; }
|
||||
public string ServiceNamespace { get; }
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
public bool UseServiceDiscovery { get; }
|
||||
public bool EnableEndpointEndpointRateLimiting { get; }
|
||||
public QoSOptions QosOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public string RequestIdKey { get; }
|
||||
public bool IsCached { get; }
|
||||
public CacheOptions CacheOptions { get; }
|
||||
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
public RateLimitOptions RateLimitOptions { get; }
|
||||
public Dictionary<string, string> RouteClaimsRequirement { get; }
|
||||
public List<ClaimToThing> ClaimsToQueries { get; }
|
||||
public List<ClaimToThing> ClaimsToHeaders { get; }
|
||||
public List<ClaimToThing> ClaimsToClaims { get; }
|
||||
public List<ClaimToThing> ClaimsToPath { get; }
|
||||
public bool IsAuthenticated { get; }
|
||||
public bool IsAuthorised { get; }
|
||||
public AuthenticationOptions AuthenticationOptions { get; }
|
||||
public DownstreamPathTemplate DownstreamPathTemplate { get; }
|
||||
public string LoadBalancerKey { get; }
|
||||
public List<string> DelegatingHandlers { get; }
|
||||
public List<AddHeader> AddHeadersToDownstream { get; }
|
||||
public List<AddHeader> AddHeadersToUpstream { get; }
|
||||
public bool DangerousAcceptAnyServerCertificateValidator { get; }
|
||||
public SecurityOptions SecurityOptions { get; }
|
||||
public string DownstreamHttpMethod { get; }
|
||||
public Version DownstreamHttpVersion { get; }
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class AggregateReRouteConfig
|
||||
{
|
||||
public string ReRouteKey { get; set; }
|
||||
public string Parameter { get; set; }
|
||||
public string JsonPath { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class AggregateRouteConfig
|
||||
{
|
||||
public string RouteKey { get; set; }
|
||||
public string Parameter { get; set; }
|
||||
public string JsonPath { get; set; }
|
||||
}
|
||||
}
|
@ -1,22 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.File
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class FileAggregateReRoute : IReRoute
|
||||
{
|
||||
public List<string> ReRouteKeys { get; set; }
|
||||
public List<AggregateReRouteConfig> ReRouteKeysConfig { get; set; }
|
||||
public string UpstreamPathTemplate { get; set; }
|
||||
public string UpstreamHost { get; set; }
|
||||
public bool ReRouteIsCaseSensitive { get; set; }
|
||||
public string Aggregator { get; set; }
|
||||
|
||||
// Only supports GET..are you crazy!! POST, PUT WOULD BE CRAZY!! :)
|
||||
public List<string> UpstreamHttpMethod
|
||||
{
|
||||
get { return new List<string> { "Get" }; }
|
||||
}
|
||||
|
||||
public int Priority { get; set; } = 1;
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class FileAggregateRoute : IRoute
|
||||
{
|
||||
public List<string> RouteKeys { get; set; }
|
||||
public List<AggregateRouteConfig> RouteKeysConfig { get; set; }
|
||||
public string UpstreamPathTemplate { get; set; }
|
||||
public string UpstreamHost { get; set; }
|
||||
public bool RouteIsCaseSensitive { get; set; }
|
||||
public string Aggregator { get; set; }
|
||||
|
||||
// Only supports GET..are you crazy!! POST, PUT WOULD BE CRAZY!! :)
|
||||
public List<string> UpstreamHttpMethod
|
||||
{
|
||||
get { return new List<string> { "Get" }; }
|
||||
}
|
||||
|
||||
public int Priority { get; set; } = 1;
|
||||
}
|
||||
}
|
@ -1,23 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class FileConfiguration
|
||||
{
|
||||
public FileConfiguration()
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>();
|
||||
GlobalConfiguration = new FileGlobalConfiguration();
|
||||
Aggregates = new List<FileAggregateReRoute>();
|
||||
DynamicReRoutes = new List<FileDynamicReRoute>();
|
||||
}
|
||||
|
||||
public List<FileReRoute> ReRoutes { get; set; }
|
||||
public List<FileDynamicReRoute> DynamicReRoutes { get; set; }
|
||||
|
||||
// Seperate field for aggregates because this let's you re-use ReRoutes in multiple Aggregates
|
||||
public List<FileAggregateReRoute> Aggregates { get; set; }
|
||||
|
||||
public FileGlobalConfiguration GlobalConfiguration { get; set; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class FileConfiguration
|
||||
{
|
||||
public FileConfiguration()
|
||||
{
|
||||
Routes = new List<FileRoute>();
|
||||
GlobalConfiguration = new FileGlobalConfiguration();
|
||||
Aggregates = new List<FileAggregateRoute>();
|
||||
DynamicRoutes = new List<FileDynamicRoute>();
|
||||
}
|
||||
|
||||
public List<FileRoute> Routes { get; set; }
|
||||
public List<FileDynamicRoute> DynamicRoutes { get; set; }
|
||||
|
||||
// Seperate field for aggregates because this let's you re-use Routes in multiple Aggregates
|
||||
public List<FileAggregateRoute> Aggregates { get; set; }
|
||||
|
||||
public FileGlobalConfiguration GlobalConfiguration { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class FileDynamicReRoute
|
||||
{
|
||||
public string ServiceName { get; set; }
|
||||
public FileRateLimitRule RateLimitRule { get; set; }
|
||||
public string DownstreamHttpVersion { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class FileDynamicRoute
|
||||
{
|
||||
public string ServiceName { get; set; }
|
||||
public FileRateLimitRule RateLimitRule { get; set; }
|
||||
public string DownstreamHttpVersion { get; set; }
|
||||
}
|
||||
}
|
@ -1,61 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration.File
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public class FileReRoute : IReRoute
|
||||
{
|
||||
public FileReRoute()
|
||||
{
|
||||
UpstreamHttpMethod = new List<string>();
|
||||
AddHeadersToRequest = new Dictionary<string, string>();
|
||||
AddClaimsToRequest = new Dictionary<string, string>();
|
||||
RouteClaimsRequirement = new Dictionary<string, string>();
|
||||
AddQueriesToRequest = new Dictionary<string, string>();
|
||||
ChangeDownstreamPathTemplate = new Dictionary<string, string>();
|
||||
DownstreamHeaderTransform = new Dictionary<string, string>();
|
||||
FileCacheOptions = new FileCacheOptions();
|
||||
QoSOptions = new FileQoSOptions();
|
||||
RateLimitOptions = new FileRateLimitRule();
|
||||
AuthenticationOptions = new FileAuthenticationOptions();
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions();
|
||||
UpstreamHeaderTransform = new Dictionary<string, string>();
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>();
|
||||
DelegatingHandlers = new List<string>();
|
||||
LoadBalancerOptions = new FileLoadBalancerOptions();
|
||||
SecurityOptions = new FileSecurityOptions();
|
||||
Priority = 1;
|
||||
}
|
||||
|
||||
public string DownstreamPathTemplate { get; set; }
|
||||
public string UpstreamPathTemplate { get; set; }
|
||||
public List<string> UpstreamHttpMethod { get; set; }
|
||||
public string DownstreamHttpMethod { get; set; }
|
||||
public Dictionary<string, string> AddHeadersToRequest { get; set; }
|
||||
public Dictionary<string, string> UpstreamHeaderTransform { get; set; }
|
||||
public Dictionary<string, string> DownstreamHeaderTransform { get; set; }
|
||||
public Dictionary<string, string> AddClaimsToRequest { get; set; }
|
||||
public Dictionary<string, string> RouteClaimsRequirement { get; set; }
|
||||
public Dictionary<string, string> AddQueriesToRequest { get; set; }
|
||||
public Dictionary<string, string> ChangeDownstreamPathTemplate { get; set; }
|
||||
public string RequestIdKey { get; set; }
|
||||
public FileCacheOptions FileCacheOptions { get; set; }
|
||||
public bool ReRouteIsCaseSensitive { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string ServiceNamespace { get; set; }
|
||||
public string DownstreamScheme { get; set; }
|
||||
public FileQoSOptions QoSOptions { get; set; }
|
||||
public FileLoadBalancerOptions LoadBalancerOptions { get; set; }
|
||||
public FileRateLimitRule RateLimitOptions { get; set; }
|
||||
public FileAuthenticationOptions AuthenticationOptions { get; set; }
|
||||
public FileHttpHandlerOptions HttpHandlerOptions { get; set; }
|
||||
public List<FileHostAndPort> DownstreamHostAndPorts { get; set; }
|
||||
public string UpstreamHost { get; set; }
|
||||
public string Key { get; set; }
|
||||
public List<string> DelegatingHandlers { get; set; }
|
||||
public int Priority { get; set; }
|
||||
public int Timeout { get; set; }
|
||||
public bool DangerousAcceptAnyServerCertificateValidator { get; set; }
|
||||
public FileSecurityOptions SecurityOptions { get; set; }
|
||||
public string DownstreamHttpVersion { get; set; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class FileRoute : IRoute
|
||||
{
|
||||
public FileRoute()
|
||||
{
|
||||
UpstreamHttpMethod = new List<string>();
|
||||
AddHeadersToRequest = new Dictionary<string, string>();
|
||||
AddClaimsToRequest = new Dictionary<string, string>();
|
||||
RouteClaimsRequirement = new Dictionary<string, string>();
|
||||
AddQueriesToRequest = new Dictionary<string, string>();
|
||||
ChangeDownstreamPathTemplate = new Dictionary<string, string>();
|
||||
DownstreamHeaderTransform = new Dictionary<string, string>();
|
||||
FileCacheOptions = new FileCacheOptions();
|
||||
QoSOptions = new FileQoSOptions();
|
||||
RateLimitOptions = new FileRateLimitRule();
|
||||
AuthenticationOptions = new FileAuthenticationOptions();
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions();
|
||||
UpstreamHeaderTransform = new Dictionary<string, string>();
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>();
|
||||
DelegatingHandlers = new List<string>();
|
||||
LoadBalancerOptions = new FileLoadBalancerOptions();
|
||||
SecurityOptions = new FileSecurityOptions();
|
||||
Priority = 1;
|
||||
}
|
||||
|
||||
public string DownstreamPathTemplate { get; set; }
|
||||
public string UpstreamPathTemplate { get; set; }
|
||||
public List<string> UpstreamHttpMethod { get; set; }
|
||||
public string DownstreamHttpMethod { get; set; }
|
||||
public Dictionary<string, string> AddHeadersToRequest { get; set; }
|
||||
public Dictionary<string, string> UpstreamHeaderTransform { get; set; }
|
||||
public Dictionary<string, string> DownstreamHeaderTransform { get; set; }
|
||||
public Dictionary<string, string> AddClaimsToRequest { get; set; }
|
||||
public Dictionary<string, string> RouteClaimsRequirement { get; set; }
|
||||
public Dictionary<string, string> AddQueriesToRequest { get; set; }
|
||||
public Dictionary<string, string> ChangeDownstreamPathTemplate { get; set; }
|
||||
public string RequestIdKey { get; set; }
|
||||
public FileCacheOptions FileCacheOptions { get; set; }
|
||||
public bool RouteIsCaseSensitive { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string ServiceNamespace { get; set; }
|
||||
public string DownstreamScheme { get; set; }
|
||||
public FileQoSOptions QoSOptions { get; set; }
|
||||
public FileLoadBalancerOptions LoadBalancerOptions { get; set; }
|
||||
public FileRateLimitRule RateLimitOptions { get; set; }
|
||||
public FileAuthenticationOptions AuthenticationOptions { get; set; }
|
||||
public FileHttpHandlerOptions HttpHandlerOptions { get; set; }
|
||||
public List<FileHostAndPort> DownstreamHostAndPorts { get; set; }
|
||||
public string UpstreamHost { get; set; }
|
||||
public string Key { get; set; }
|
||||
public List<string> DelegatingHandlers { get; set; }
|
||||
public int Priority { get; set; }
|
||||
public int Timeout { get; set; }
|
||||
public bool DangerousAcceptAnyServerCertificateValidator { get; set; }
|
||||
public FileSecurityOptions SecurityOptions { get; set; }
|
||||
public string DownstreamHttpVersion { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public interface IReRoute
|
||||
{
|
||||
string UpstreamPathTemplate { get; set; }
|
||||
bool ReRouteIsCaseSensitive { get; set; }
|
||||
int Priority { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.File
|
||||
{
|
||||
public interface IRoute
|
||||
{
|
||||
string UpstreamPathTemplate { get; set; }
|
||||
bool RouteIsCaseSensitive { get; set; }
|
||||
int Priority { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
using System;
|
||||
|
||||
public interface IInternalConfiguration
|
||||
{
|
||||
List<ReRoute> ReRoutes { get; }
|
||||
|
||||
string AdministrationPath { get; }
|
||||
|
||||
ServiceProviderConfiguration ServiceProviderConfiguration { get; }
|
||||
|
||||
string RequestId { get; }
|
||||
|
||||
LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
|
||||
string DownstreamScheme { get; }
|
||||
|
||||
QoSOptions QoSOptions { get; }
|
||||
|
||||
HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
|
||||
Version DownstreamHttpVersion { get; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
using System;
|
||||
|
||||
public interface IInternalConfiguration
|
||||
{
|
||||
List<Route> Routes { get; }
|
||||
|
||||
string AdministrationPath { get; }
|
||||
|
||||
ServiceProviderConfiguration ServiceProviderConfiguration { get; }
|
||||
|
||||
string RequestId { get; }
|
||||
|
||||
LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
|
||||
string DownstreamScheme { get; }
|
||||
|
||||
QoSOptions QoSOptions { get; }
|
||||
|
||||
HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
|
||||
Version DownstreamHttpVersion { get; }
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
using System;
|
||||
|
||||
public class InternalConfiguration : IInternalConfiguration
|
||||
{
|
||||
public InternalConfiguration(
|
||||
List<ReRoute> reRoutes,
|
||||
string administrationPath,
|
||||
ServiceProviderConfiguration serviceProviderConfiguration,
|
||||
string requestId,
|
||||
LoadBalancerOptions loadBalancerOptions,
|
||||
string downstreamScheme,
|
||||
QoSOptions qoSOptions,
|
||||
HttpHandlerOptions httpHandlerOptions,
|
||||
Version downstreamHttpVersion)
|
||||
{
|
||||
ReRoutes = reRoutes;
|
||||
AdministrationPath = administrationPath;
|
||||
ServiceProviderConfiguration = serviceProviderConfiguration;
|
||||
RequestId = requestId;
|
||||
LoadBalancerOptions = loadBalancerOptions;
|
||||
DownstreamScheme = downstreamScheme;
|
||||
QoSOptions = qoSOptions;
|
||||
HttpHandlerOptions = httpHandlerOptions;
|
||||
DownstreamHttpVersion = downstreamHttpVersion;
|
||||
}
|
||||
|
||||
public List<ReRoute> ReRoutes { get; }
|
||||
public string AdministrationPath { get; }
|
||||
public ServiceProviderConfiguration ServiceProviderConfiguration { get; }
|
||||
public string RequestId { get; }
|
||||
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public QoSOptions QoSOptions { get; }
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
|
||||
public Version DownstreamHttpVersion { get; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
using System;
|
||||
|
||||
public class InternalConfiguration : IInternalConfiguration
|
||||
{
|
||||
public InternalConfiguration(
|
||||
List<Route> routes,
|
||||
string administrationPath,
|
||||
ServiceProviderConfiguration serviceProviderConfiguration,
|
||||
string requestId,
|
||||
LoadBalancerOptions loadBalancerOptions,
|
||||
string downstreamScheme,
|
||||
QoSOptions qoSOptions,
|
||||
HttpHandlerOptions httpHandlerOptions,
|
||||
Version downstreamHttpVersion)
|
||||
{
|
||||
Routes = routes;
|
||||
AdministrationPath = administrationPath;
|
||||
ServiceProviderConfiguration = serviceProviderConfiguration;
|
||||
RequestId = requestId;
|
||||
LoadBalancerOptions = loadBalancerOptions;
|
||||
DownstreamScheme = downstreamScheme;
|
||||
QoSOptions = qoSOptions;
|
||||
HttpHandlerOptions = httpHandlerOptions;
|
||||
DownstreamHttpVersion = downstreamHttpVersion;
|
||||
}
|
||||
|
||||
public List<Route> Routes { get; }
|
||||
public string AdministrationPath { get; }
|
||||
public ServiceProviderConfiguration ServiceProviderConfiguration { get; }
|
||||
public string RequestId { get; }
|
||||
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public QoSOptions QoSOptions { get; }
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
|
||||
public Version DownstreamHttpVersion { get; }
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
|
||||
public class ReRoute
|
||||
public class Route
|
||||
{
|
||||
public ReRoute(List<DownstreamReRoute> downstreamReRoute,
|
||||
List<AggregateReRouteConfig> downstreamReRouteConfig,
|
||||
public Route(List<DownstreamRoute> downstreamRoute,
|
||||
List<AggregateRouteConfig> downstreamRouteConfig,
|
||||
List<HttpMethod> upstreamHttpMethod,
|
||||
UpstreamPathTemplate upstreamTemplatePattern,
|
||||
string upstreamHost,
|
||||
string aggregator)
|
||||
{
|
||||
UpstreamHost = upstreamHost;
|
||||
DownstreamReRoute = downstreamReRoute;
|
||||
DownstreamReRouteConfig = downstreamReRouteConfig;
|
||||
DownstreamRoute = downstreamRoute;
|
||||
DownstreamRouteConfig = downstreamRouteConfig;
|
||||
UpstreamHttpMethod = upstreamHttpMethod;
|
||||
UpstreamTemplatePattern = upstreamTemplatePattern;
|
||||
Aggregator = aggregator;
|
||||
@ -25,8 +25,8 @@
|
||||
public UpstreamPathTemplate UpstreamTemplatePattern { get; private set; }
|
||||
public List<HttpMethod> UpstreamHttpMethod { get; private set; }
|
||||
public string UpstreamHost { get; private set; }
|
||||
public List<DownstreamReRoute> DownstreamReRoute { get; private set; }
|
||||
public List<AggregateReRouteConfig> DownstreamReRouteConfig { get; private set; }
|
||||
public List<DownstreamRoute> DownstreamRoute { get; private set; }
|
||||
public List<AggregateRouteConfig> DownstreamRouteConfig { get; private set; }
|
||||
public string Aggregator { get; private set; }
|
||||
}
|
||||
}
|
@ -1,20 +1,20 @@
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
public class ReRouteOptions
|
||||
{
|
||||
public ReRouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isEnableRateLimiting, bool useServiceDiscovery)
|
||||
{
|
||||
IsAuthenticated = isAuthenticated;
|
||||
IsAuthorised = isAuthorised;
|
||||
IsCached = isCached;
|
||||
EnableRateLimiting = isEnableRateLimiting;
|
||||
UseServiceDiscovery = useServiceDiscovery;
|
||||
}
|
||||
|
||||
public bool IsAuthenticated { get; private set; }
|
||||
public bool IsAuthorised { get; private set; }
|
||||
public bool IsCached { get; private set; }
|
||||
public bool EnableRateLimiting { get; private set; }
|
||||
public bool UseServiceDiscovery { get; private set; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
public class RouteOptions
|
||||
{
|
||||
public RouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isEnableRateLimiting, bool useServiceDiscovery)
|
||||
{
|
||||
IsAuthenticated = isAuthenticated;
|
||||
IsAuthorised = isAuthorised;
|
||||
IsCached = isCached;
|
||||
EnableRateLimiting = isEnableRateLimiting;
|
||||
UseServiceDiscovery = useServiceDiscovery;
|
||||
}
|
||||
|
||||
public bool IsAuthenticated { get; private set; }
|
||||
public bool IsAuthorised { get; private set; }
|
||||
public bool IsCached { get; private set; }
|
||||
public bool EnableRateLimiting { get; private set; }
|
||||
public bool UseServiceDiscovery { get; private set; }
|
||||
}
|
||||
}
|
@ -1,184 +1,184 @@
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using Errors;
|
||||
using File;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Responses;
|
||||
using ServiceDiscovery;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator
|
||||
{
|
||||
private readonly List<ServiceDiscoveryFinderDelegate> _serviceDiscoveryFinderDelegates;
|
||||
|
||||
public FileConfigurationFluentValidator(IServiceProvider provider, ReRouteFluentValidator reRouteFluentValidator, FileGlobalConfigurationFluentValidator fileGlobalConfigurationFluentValidator)
|
||||
{
|
||||
_serviceDiscoveryFinderDelegates = provider
|
||||
.GetServices<ServiceDiscoveryFinderDelegate>()
|
||||
.ToList();
|
||||
|
||||
RuleForEach(configuration => configuration.ReRoutes)
|
||||
.SetValidator(reRouteFluentValidator);
|
||||
|
||||
RuleFor(configuration => configuration.GlobalConfiguration)
|
||||
.SetValidator(fileGlobalConfigurationFluentValidator);
|
||||
|
||||
RuleForEach(configuration => configuration.ReRoutes)
|
||||
.Must((config, reRoute) => IsNotDuplicateIn(reRoute, config.ReRoutes))
|
||||
.WithMessage((config, reRoute) => $"{nameof(reRoute)} {reRoute.UpstreamPathTemplate} has duplicate");
|
||||
|
||||
RuleForEach(configuration => configuration.ReRoutes)
|
||||
.Must((config, reRoute) => HaveServiceDiscoveryProviderRegistered(reRoute, config.GlobalConfiguration.ServiceDiscoveryProvider))
|
||||
.WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
|
||||
|
||||
RuleForEach(configuration => configuration.ReRoutes)
|
||||
.Must((config, reRoute) => IsPlaceholderNotDuplicatedIn(reRoute.UpstreamPathTemplate))
|
||||
.WithMessage((config, reRoute) => $"{nameof(reRoute)} {reRoute.UpstreamPathTemplate} has duplicated placeholder");
|
||||
|
||||
RuleFor(configuration => configuration.GlobalConfiguration.ServiceDiscoveryProvider)
|
||||
.Must(HaveServiceDiscoveryProviderRegistered)
|
||||
.WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
|
||||
|
||||
RuleForEach(configuration => configuration.ReRoutes)
|
||||
.Must((config, reRoute) => IsNotDuplicateIn(reRoute, config.Aggregates))
|
||||
.WithMessage((config, reRoute) => $"{nameof(reRoute)} {reRoute.UpstreamPathTemplate} has duplicate aggregate");
|
||||
|
||||
RuleForEach(configuration => configuration.Aggregates)
|
||||
.Must((config, aggregateReRoute) => IsNotDuplicateIn(aggregateReRoute, config.Aggregates))
|
||||
.WithMessage((config, aggregate) => $"{nameof(aggregate)} {aggregate.UpstreamPathTemplate} has duplicate aggregate");
|
||||
|
||||
RuleForEach(configuration => configuration.Aggregates)
|
||||
.Must((config, aggregateReRoute) => AllReRoutesForAggregateExist(aggregateReRoute, config.ReRoutes))
|
||||
.WithMessage((config, aggregateReRoute) => $"ReRoutes for {nameof(aggregateReRoute)} {aggregateReRoute.UpstreamPathTemplate} either do not exist or do not have correct ServiceName property");
|
||||
|
||||
RuleForEach(configuration => configuration.Aggregates)
|
||||
.Must((config, aggregateReRoute) => DoesNotContainReRoutesWithSpecificRequestIdKeys(aggregateReRoute, config.ReRoutes))
|
||||
.WithMessage((config, aggregateReRoute) => $"{nameof(aggregateReRoute)} {aggregateReRoute.UpstreamPathTemplate} contains ReRoute with specific RequestIdKey, this is not possible with Aggregates");
|
||||
}
|
||||
|
||||
private bool HaveServiceDiscoveryProviderRegistered(FileReRoute reRoute, FileServiceDiscoveryProvider serviceDiscoveryProvider)
|
||||
{
|
||||
if (string.IsNullOrEmpty(reRoute.ServiceName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (serviceDiscoveryProvider?.Type?.ToLower() == "servicefabric")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return _serviceDiscoveryFinderDelegates.Any();
|
||||
}
|
||||
|
||||
private bool HaveServiceDiscoveryProviderRegistered(FileServiceDiscoveryProvider serviceDiscoveryProvider)
|
||||
{
|
||||
if (serviceDiscoveryProvider == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (serviceDiscoveryProvider?.Type?.ToLower() == "servicefabric")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(serviceDiscoveryProvider.Type) || _serviceDiscoveryFinderDelegates.Any();
|
||||
}
|
||||
|
||||
public async Task<Response<ConfigurationValidationResult>> IsValid(FileConfiguration configuration)
|
||||
{
|
||||
var validateResult = await ValidateAsync(configuration);
|
||||
|
||||
if (validateResult.IsValid)
|
||||
{
|
||||
return new OkResponse<ConfigurationValidationResult>(new ConfigurationValidationResult(false));
|
||||
}
|
||||
|
||||
var errors = validateResult.Errors.Select(failure => new FileValidationFailedError(failure.ErrorMessage));
|
||||
|
||||
var result = new ConfigurationValidationResult(true, errors.Cast<Error>().ToList());
|
||||
|
||||
return new OkResponse<ConfigurationValidationResult>(result);
|
||||
}
|
||||
|
||||
private bool AllReRoutesForAggregateExist(FileAggregateReRoute fileAggregateReRoute, List<FileReRoute> reRoutes)
|
||||
{
|
||||
var reRoutesForAggregate = reRoutes.Where(r => fileAggregateReRoute.ReRouteKeys.Contains(r.Key));
|
||||
|
||||
return reRoutesForAggregate.Count() == fileAggregateReRoute.ReRouteKeys.Count;
|
||||
}
|
||||
|
||||
private bool IsPlaceholderNotDuplicatedIn(string upstreamPathTemplate)
|
||||
{
|
||||
Regex regExPlaceholder = new Regex("{[^}]+}");
|
||||
var matches = regExPlaceholder.Matches(upstreamPathTemplate);
|
||||
var upstreamPathPlaceholders = matches.Select(m => m.Value);
|
||||
return upstreamPathPlaceholders.Count() == upstreamPathPlaceholders.Distinct().Count();
|
||||
}
|
||||
|
||||
private static bool DoesNotContainReRoutesWithSpecificRequestIdKeys(FileAggregateReRoute fileAggregateReRoute,
|
||||
List<FileReRoute> reRoutes)
|
||||
{
|
||||
var reRoutesForAggregate = reRoutes.Where(r => fileAggregateReRoute.ReRouteKeys.Contains(r.Key));
|
||||
|
||||
return reRoutesForAggregate.All(r => string.IsNullOrEmpty(r.RequestIdKey));
|
||||
}
|
||||
|
||||
private static bool IsNotDuplicateIn(FileReRoute reRoute,
|
||||
List<FileReRoute> reRoutes)
|
||||
{
|
||||
var matchingReRoutes = reRoutes
|
||||
.Where(r => r.UpstreamPathTemplate == reRoute.UpstreamPathTemplate
|
||||
&& r.UpstreamHost == reRoute.UpstreamHost)
|
||||
.ToList();
|
||||
|
||||
if (matchingReRoutes.Count == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var allowAllVerbs = matchingReRoutes.Any(x => x.UpstreamHttpMethod.Count == 0);
|
||||
|
||||
var duplicateAllowAllVerbs = matchingReRoutes.Count(x => x.UpstreamHttpMethod.Count == 0) > 1;
|
||||
|
||||
var specificVerbs = matchingReRoutes.Any(x => x.UpstreamHttpMethod.Count != 0);
|
||||
|
||||
var duplicateSpecificVerbs = matchingReRoutes.SelectMany(x => x.UpstreamHttpMethod).GroupBy(x => x.ToLower()).SelectMany(x => x.Skip(1)).Any();
|
||||
|
||||
if (duplicateAllowAllVerbs || duplicateSpecificVerbs || (allowAllVerbs && specificVerbs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsNotDuplicateIn(FileReRoute reRoute,
|
||||
List<FileAggregateReRoute> aggregateReRoutes)
|
||||
{
|
||||
var duplicate = aggregateReRoutes
|
||||
.Any(a => a.UpstreamPathTemplate == reRoute.UpstreamPathTemplate
|
||||
&& a.UpstreamHost == reRoute.UpstreamHost
|
||||
&& reRoute.UpstreamHttpMethod.Select(x => x.ToLower()).Contains("get"));
|
||||
|
||||
return !duplicate;
|
||||
}
|
||||
|
||||
private static bool IsNotDuplicateIn(FileAggregateReRoute reRoute,
|
||||
List<FileAggregateReRoute> aggregateReRoutes)
|
||||
{
|
||||
var matchingReRoutes = aggregateReRoutes
|
||||
.Where(r => r.UpstreamPathTemplate == reRoute.UpstreamPathTemplate
|
||||
&& r.UpstreamHost == reRoute.UpstreamHost)
|
||||
.ToList();
|
||||
|
||||
return matchingReRoutes.Count <= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using Errors;
|
||||
using File;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Responses;
|
||||
using ServiceDiscovery;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator
|
||||
{
|
||||
private readonly List<ServiceDiscoveryFinderDelegate> _serviceDiscoveryFinderDelegates;
|
||||
|
||||
public FileConfigurationFluentValidator(IServiceProvider provider, RouteFluentValidator routeFluentValidator, FileGlobalConfigurationFluentValidator fileGlobalConfigurationFluentValidator)
|
||||
{
|
||||
_serviceDiscoveryFinderDelegates = provider
|
||||
.GetServices<ServiceDiscoveryFinderDelegate>()
|
||||
.ToList();
|
||||
|
||||
RuleForEach(configuration => configuration.Routes)
|
||||
.SetValidator(routeFluentValidator);
|
||||
|
||||
RuleFor(configuration => configuration.GlobalConfiguration)
|
||||
.SetValidator(fileGlobalConfigurationFluentValidator);
|
||||
|
||||
RuleForEach(configuration => configuration.Routes)
|
||||
.Must((config, route) => IsNotDuplicateIn(route, config.Routes))
|
||||
.WithMessage((config, route) => $"{nameof(route)} {route.UpstreamPathTemplate} has duplicate");
|
||||
|
||||
RuleForEach(configuration => configuration.Routes)
|
||||
.Must((config, route) => HaveServiceDiscoveryProviderRegistered(route, config.GlobalConfiguration.ServiceDiscoveryProvider))
|
||||
.WithMessage((config, route) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a Route or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
|
||||
|
||||
RuleForEach(configuration => configuration.Routes)
|
||||
.Must((config, route) => IsPlaceholderNotDuplicatedIn(route.UpstreamPathTemplate))
|
||||
.WithMessage((config, route) => $"{nameof(route)} {route.UpstreamPathTemplate} has duplicated placeholder");
|
||||
|
||||
RuleFor(configuration => configuration.GlobalConfiguration.ServiceDiscoveryProvider)
|
||||
.Must(HaveServiceDiscoveryProviderRegistered)
|
||||
.WithMessage((config, route) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a Route or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
|
||||
|
||||
RuleForEach(configuration => configuration.Routes)
|
||||
.Must((config, route) => IsNotDuplicateIn(route, config.Aggregates))
|
||||
.WithMessage((config, route) => $"{nameof(route)} {route.UpstreamPathTemplate} has duplicate aggregate");
|
||||
|
||||
RuleForEach(configuration => configuration.Aggregates)
|
||||
.Must((config, aggregateRoute) => IsNotDuplicateIn(aggregateRoute, config.Aggregates))
|
||||
.WithMessage((config, aggregate) => $"{nameof(aggregate)} {aggregate.UpstreamPathTemplate} has duplicate aggregate");
|
||||
|
||||
RuleForEach(configuration => configuration.Aggregates)
|
||||
.Must((config, aggregateRoute) => AllRoutesForAggregateExist(aggregateRoute, config.Routes))
|
||||
.WithMessage((config, aggregateRoute) => $"Routes for {nameof(aggregateRoute)} {aggregateRoute.UpstreamPathTemplate} either do not exist or do not have correct ServiceName property");
|
||||
|
||||
RuleForEach(configuration => configuration.Aggregates)
|
||||
.Must((config, aggregateRoute) => DoesNotContainRoutesWithSpecificRequestIdKeys(aggregateRoute, config.Routes))
|
||||
.WithMessage((config, aggregateRoute) => $"{nameof(aggregateRoute)} {aggregateRoute.UpstreamPathTemplate} contains Route with specific RequestIdKey, this is not possible with Aggregates");
|
||||
}
|
||||
|
||||
private bool HaveServiceDiscoveryProviderRegistered(FileRoute route, FileServiceDiscoveryProvider serviceDiscoveryProvider)
|
||||
{
|
||||
if (string.IsNullOrEmpty(route.ServiceName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (serviceDiscoveryProvider?.Type?.ToLower() == "servicefabric")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return _serviceDiscoveryFinderDelegates.Any();
|
||||
}
|
||||
|
||||
private bool HaveServiceDiscoveryProviderRegistered(FileServiceDiscoveryProvider serviceDiscoveryProvider)
|
||||
{
|
||||
if (serviceDiscoveryProvider == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (serviceDiscoveryProvider?.Type?.ToLower() == "servicefabric")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(serviceDiscoveryProvider.Type) || _serviceDiscoveryFinderDelegates.Any();
|
||||
}
|
||||
|
||||
public async Task<Response<ConfigurationValidationResult>> IsValid(FileConfiguration configuration)
|
||||
{
|
||||
var validateResult = await ValidateAsync(configuration);
|
||||
|
||||
if (validateResult.IsValid)
|
||||
{
|
||||
return new OkResponse<ConfigurationValidationResult>(new ConfigurationValidationResult(false));
|
||||
}
|
||||
|
||||
var errors = validateResult.Errors.Select(failure => new FileValidationFailedError(failure.ErrorMessage));
|
||||
|
||||
var result = new ConfigurationValidationResult(true, errors.Cast<Error>().ToList());
|
||||
|
||||
return new OkResponse<ConfigurationValidationResult>(result);
|
||||
}
|
||||
|
||||
private bool AllRoutesForAggregateExist(FileAggregateRoute fileAggregateRoute, List<FileRoute> routes)
|
||||
{
|
||||
var routesForAggregate = routes.Where(r => fileAggregateRoute.RouteKeys.Contains(r.Key));
|
||||
|
||||
return routesForAggregate.Count() == fileAggregateRoute.RouteKeys.Count;
|
||||
}
|
||||
|
||||
private bool IsPlaceholderNotDuplicatedIn(string upstreamPathTemplate)
|
||||
{
|
||||
Regex regExPlaceholder = new Regex("{[^}]+}");
|
||||
var matches = regExPlaceholder.Matches(upstreamPathTemplate);
|
||||
var upstreamPathPlaceholders = matches.Select(m => m.Value);
|
||||
return upstreamPathPlaceholders.Count() == upstreamPathPlaceholders.Distinct().Count();
|
||||
}
|
||||
|
||||
private static bool DoesNotContainRoutesWithSpecificRequestIdKeys(FileAggregateRoute fileAggregateRoute,
|
||||
List<FileRoute> routes)
|
||||
{
|
||||
var routesForAggregate = routes.Where(r => fileAggregateRoute.RouteKeys.Contains(r.Key));
|
||||
|
||||
return routesForAggregate.All(r => string.IsNullOrEmpty(r.RequestIdKey));
|
||||
}
|
||||
|
||||
private static bool IsNotDuplicateIn(FileRoute route,
|
||||
List<FileRoute> routes)
|
||||
{
|
||||
var matchingRoutes = routes
|
||||
.Where(r => r.UpstreamPathTemplate == route.UpstreamPathTemplate
|
||||
&& r.UpstreamHost == route.UpstreamHost)
|
||||
.ToList();
|
||||
|
||||
if (matchingRoutes.Count == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var allowAllVerbs = matchingRoutes.Any(x => x.UpstreamHttpMethod.Count == 0);
|
||||
|
||||
var duplicateAllowAllVerbs = matchingRoutes.Count(x => x.UpstreamHttpMethod.Count == 0) > 1;
|
||||
|
||||
var specificVerbs = matchingRoutes.Any(x => x.UpstreamHttpMethod.Count != 0);
|
||||
|
||||
var duplicateSpecificVerbs = matchingRoutes.SelectMany(x => x.UpstreamHttpMethod).GroupBy(x => x.ToLower()).SelectMany(x => x.Skip(1)).Any();
|
||||
|
||||
if (duplicateAllowAllVerbs || duplicateSpecificVerbs || (allowAllVerbs && specificVerbs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsNotDuplicateIn(FileRoute route,
|
||||
List<FileAggregateRoute> aggregateRoutes)
|
||||
{
|
||||
var duplicate = aggregateRoutes
|
||||
.Any(a => a.UpstreamPathTemplate == route.UpstreamPathTemplate
|
||||
&& a.UpstreamHost == route.UpstreamHost
|
||||
&& route.UpstreamHttpMethod.Select(x => x.ToLower()).Contains("get"));
|
||||
|
||||
return !duplicate;
|
||||
}
|
||||
|
||||
private static bool IsNotDuplicateIn(FileAggregateRoute route,
|
||||
List<FileAggregateRoute> aggregateRoutes)
|
||||
{
|
||||
var matchingRoutes = aggregateRoutes
|
||||
.Where(r => r.UpstreamPathTemplate == route.UpstreamPathTemplate
|
||||
&& r.UpstreamHost == route.UpstreamHost)
|
||||
.ToList();
|
||||
|
||||
return matchingRoutes.Count <= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,30 @@
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using File;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Requester;
|
||||
using System;
|
||||
|
||||
public class FileQoSOptionsFluentValidator : AbstractValidator<FileQoSOptions>
|
||||
{
|
||||
private readonly QosDelegatingHandlerDelegate _qosDelegatingHandlerDelegate;
|
||||
|
||||
public FileQoSOptionsFluentValidator(IServiceProvider provider)
|
||||
{
|
||||
_qosDelegatingHandlerDelegate = provider.GetService<QosDelegatingHandlerDelegate>();
|
||||
|
||||
When(qosOptions => qosOptions.TimeoutValue > 0 && qosOptions.ExceptionsAllowedBeforeBreaking > 0, () =>
|
||||
{
|
||||
RuleFor(qosOptions => qosOptions)
|
||||
.Must(HaveQosHandlerRegistered)
|
||||
.WithMessage("Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using QoSOptions but no QosDelegatingHandlerDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Polly and services.AddPolly()?");
|
||||
});
|
||||
}
|
||||
|
||||
private bool HaveQosHandlerRegistered(FileQoSOptions arg)
|
||||
{
|
||||
return _qosDelegatingHandlerDelegate != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using File;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Requester;
|
||||
using System;
|
||||
|
||||
public class FileQoSOptionsFluentValidator : AbstractValidator<FileQoSOptions>
|
||||
{
|
||||
private readonly QosDelegatingHandlerDelegate _qosDelegatingHandlerDelegate;
|
||||
|
||||
public FileQoSOptionsFluentValidator(IServiceProvider provider)
|
||||
{
|
||||
_qosDelegatingHandlerDelegate = provider.GetService<QosDelegatingHandlerDelegate>();
|
||||
|
||||
When(qosOptions => qosOptions.TimeoutValue > 0 && qosOptions.ExceptionsAllowedBeforeBreaking > 0, () =>
|
||||
{
|
||||
RuleFor(qosOptions => qosOptions)
|
||||
.Must(HaveQosHandlerRegistered)
|
||||
.WithMessage("Unable to start Ocelot because either a Route or GlobalConfiguration are using QoSOptions but no QosDelegatingHandlerDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Polly and services.AddPolly()?");
|
||||
});
|
||||
}
|
||||
|
||||
private bool HaveQosHandlerRegistered(FileQoSOptions arg)
|
||||
{
|
||||
return _qosDelegatingHandlerDelegate != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using FluentValidation;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
public class HostAndPortValidator : AbstractValidator<FileHostAndPort>
|
||||
{
|
||||
public HostAndPortValidator()
|
||||
{
|
||||
RuleFor(r => r.Host)
|
||||
.NotEmpty()
|
||||
.WithMessage("When not using service discovery Host must be set on DownstreamHostAndPorts if you are not using ReRoute.Host or Ocelot cannot find your service!");
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using FluentValidation;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
public class HostAndPortValidator : AbstractValidator<FileHostAndPort>
|
||||
{
|
||||
public HostAndPortValidator()
|
||||
{
|
||||
RuleFor(r => r.Host)
|
||||
.NotEmpty()
|
||||
.WithMessage("When not using service discovery Host must be set on DownstreamHostAndPorts if you are not using Route.Host or Ocelot cannot find your service!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,127 +1,127 @@
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using File;
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class ReRouteFluentValidator : AbstractValidator<FileReRoute>
|
||||
{
|
||||
private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;
|
||||
|
||||
public ReRouteFluentValidator(IAuthenticationSchemeProvider authenticationSchemeProvider, HostAndPortValidator hostAndPortValidator, FileQoSOptionsFluentValidator fileQoSOptionsFluentValidator)
|
||||
{
|
||||
_authenticationSchemeProvider = authenticationSchemeProvider;
|
||||
|
||||
RuleFor(reRoute => reRoute.QoSOptions)
|
||||
.SetValidator(fileQoSOptionsFluentValidator);
|
||||
|
||||
RuleFor(reRoute => reRoute.DownstreamPathTemplate)
|
||||
.NotEmpty()
|
||||
.WithMessage("{PropertyName} cannot be empty");
|
||||
|
||||
RuleFor(reRoute => reRoute.UpstreamPathTemplate)
|
||||
.NotEmpty()
|
||||
.WithMessage("{PropertyName} cannot be empty");
|
||||
|
||||
When(reRoute => !string.IsNullOrEmpty(reRoute.DownstreamPathTemplate), () =>
|
||||
{
|
||||
RuleFor(reRoute => reRoute.DownstreamPathTemplate)
|
||||
.Must(path => path.StartsWith("/"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} doesnt start with forward slash");
|
||||
|
||||
RuleFor(reRoute => reRoute.DownstreamPathTemplate)
|
||||
.Must(path => !path.Contains("//"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains double forward slash, Ocelot does not support this at the moment. Please raise an issue in GitHib if you need this feature.");
|
||||
|
||||
RuleFor(reRoute => reRoute.DownstreamPathTemplate)
|
||||
.Must(path => !path.Contains("https://") && !path.Contains("http://"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains scheme");
|
||||
});
|
||||
|
||||
When(reRoute => !string.IsNullOrEmpty(reRoute.UpstreamPathTemplate), () =>
|
||||
{
|
||||
RuleFor(reRoute => reRoute.UpstreamPathTemplate)
|
||||
.Must(path => !path.Contains("//"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains double forward slash, Ocelot does not support this at the moment. Please raise an issue in GitHib if you need this feature.");
|
||||
|
||||
RuleFor(reRoute => reRoute.UpstreamPathTemplate)
|
||||
.Must(path => path.StartsWith("/"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} doesnt start with forward slash");
|
||||
|
||||
RuleFor(reRoute => reRoute.UpstreamPathTemplate)
|
||||
.Must(path => !path.Contains("https://") && !path.Contains("http://"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains scheme");
|
||||
});
|
||||
|
||||
When(reRoute => reRoute.RateLimitOptions.EnableRateLimiting, () =>
|
||||
{
|
||||
RuleFor(reRoute => reRoute.RateLimitOptions.Period)
|
||||
.NotEmpty()
|
||||
.WithMessage("RateLimitOptions.Period is empty");
|
||||
|
||||
RuleFor(reRoute => reRoute.RateLimitOptions)
|
||||
.Must(IsValidPeriod)
|
||||
.WithMessage("RateLimitOptions.Period does not contain integer then s (second), m (minute), h (hour), d (day) e.g. 1m for 1 minute period");
|
||||
});
|
||||
|
||||
RuleFor(reRoute => reRoute.AuthenticationOptions)
|
||||
.MustAsync(IsSupportedAuthenticationProviders)
|
||||
.WithMessage("{PropertyName} {PropertyValue} is unsupported authentication provider");
|
||||
|
||||
When(reRoute => string.IsNullOrEmpty(reRoute.ServiceName), () =>
|
||||
{
|
||||
RuleFor(r => r.DownstreamHostAndPorts).NotEmpty()
|
||||
.WithMessage("When not using service discovery DownstreamHostAndPorts must be set and not empty or Ocelot cannot find your service!");
|
||||
});
|
||||
|
||||
When(reRoute => string.IsNullOrEmpty(reRoute.ServiceName), () =>
|
||||
{
|
||||
RuleForEach(reRoute => reRoute.DownstreamHostAndPorts)
|
||||
.SetValidator(hostAndPortValidator);
|
||||
});
|
||||
|
||||
When(reRoute => !string.IsNullOrEmpty(reRoute.DownstreamHttpVersion), () =>
|
||||
{
|
||||
RuleFor(r => r.DownstreamHttpVersion).Matches("^[0-9]([.,][0-9]{1,1})?$");
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> IsSupportedAuthenticationProviders(FileAuthenticationOptions authenticationOptions, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(authenticationOptions.AuthenticationProviderKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var schemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
|
||||
|
||||
var supportedSchemes = schemes.Select(scheme => scheme.Name).ToList();
|
||||
|
||||
return supportedSchemes.Contains(authenticationOptions.AuthenticationProviderKey);
|
||||
}
|
||||
|
||||
private static bool IsValidPeriod(FileRateLimitRule rateLimitOptions)
|
||||
{
|
||||
if (string.IsNullOrEmpty(rateLimitOptions.Period))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var period = rateLimitOptions.Period;
|
||||
|
||||
var secondsRegEx = new Regex("^[0-9]+s");
|
||||
var minutesRegEx = new Regex("^[0-9]+m");
|
||||
var hoursRegEx = new Regex("^[0-9]+h");
|
||||
var daysRegEx = new Regex("^[0-9]+d");
|
||||
|
||||
return secondsRegEx.Match(period).Success
|
||||
|| minutesRegEx.Match(period).Success
|
||||
|| hoursRegEx.Match(period).Success
|
||||
|| daysRegEx.Match(period).Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Configuration.Validator
|
||||
{
|
||||
using Ocelot.Configuration.File;
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class RouteFluentValidator : AbstractValidator<FileRoute>
|
||||
{
|
||||
private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;
|
||||
|
||||
public RouteFluentValidator(IAuthenticationSchemeProvider authenticationSchemeProvider, HostAndPortValidator hostAndPortValidator, FileQoSOptionsFluentValidator fileQoSOptionsFluentValidator)
|
||||
{
|
||||
_authenticationSchemeProvider = authenticationSchemeProvider;
|
||||
|
||||
RuleFor(route => route.QoSOptions)
|
||||
.SetValidator(fileQoSOptionsFluentValidator);
|
||||
|
||||
RuleFor(route => route.DownstreamPathTemplate)
|
||||
.NotEmpty()
|
||||
.WithMessage("{PropertyName} cannot be empty");
|
||||
|
||||
RuleFor(route => route.UpstreamPathTemplate)
|
||||
.NotEmpty()
|
||||
.WithMessage("{PropertyName} cannot be empty");
|
||||
|
||||
When(route => !string.IsNullOrEmpty(route.DownstreamPathTemplate), () =>
|
||||
{
|
||||
RuleFor(route => route.DownstreamPathTemplate)
|
||||
.Must(path => path.StartsWith("/"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} doesnt start with forward slash");
|
||||
|
||||
RuleFor(route => route.DownstreamPathTemplate)
|
||||
.Must(path => !path.Contains("//"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains double forward slash, Ocelot does not support this at the moment. Please raise an issue in GitHib if you need this feature.");
|
||||
|
||||
RuleFor(route => route.DownstreamPathTemplate)
|
||||
.Must(path => !path.Contains("https://") && !path.Contains("http://"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains scheme");
|
||||
});
|
||||
|
||||
When(route => !string.IsNullOrEmpty(route.UpstreamPathTemplate), () =>
|
||||
{
|
||||
RuleFor(route => route.UpstreamPathTemplate)
|
||||
.Must(path => !path.Contains("//"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains double forward slash, Ocelot does not support this at the moment. Please raise an issue in GitHib if you need this feature.");
|
||||
|
||||
RuleFor(route => route.UpstreamPathTemplate)
|
||||
.Must(path => path.StartsWith("/"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} doesnt start with forward slash");
|
||||
|
||||
RuleFor(route => route.UpstreamPathTemplate)
|
||||
.Must(path => !path.Contains("https://") && !path.Contains("http://"))
|
||||
.WithMessage("{PropertyName} {PropertyValue} contains scheme");
|
||||
});
|
||||
|
||||
When(route => route.RateLimitOptions.EnableRateLimiting, () =>
|
||||
{
|
||||
RuleFor(route => route.RateLimitOptions.Period)
|
||||
.NotEmpty()
|
||||
.WithMessage("RateLimitOptions.Period is empty");
|
||||
|
||||
RuleFor(route => route.RateLimitOptions)
|
||||
.Must(IsValidPeriod)
|
||||
.WithMessage("RateLimitOptions.Period does not contain integer then s (second), m (minute), h (hour), d (day) e.g. 1m for 1 minute period");
|
||||
});
|
||||
|
||||
RuleFor(route => route.AuthenticationOptions)
|
||||
.MustAsync(IsSupportedAuthenticationProviders)
|
||||
.WithMessage("{PropertyName} {PropertyValue} is unsupported authentication provider");
|
||||
|
||||
When(route => string.IsNullOrEmpty(route.ServiceName), () =>
|
||||
{
|
||||
RuleFor(r => r.DownstreamHostAndPorts).NotEmpty()
|
||||
.WithMessage("When not using service discovery DownstreamHostAndPorts must be set and not empty or Ocelot cannot find your service!");
|
||||
});
|
||||
|
||||
When(route => string.IsNullOrEmpty(route.ServiceName), () =>
|
||||
{
|
||||
RuleForEach(route => route.DownstreamHostAndPorts)
|
||||
.SetValidator(hostAndPortValidator);
|
||||
});
|
||||
|
||||
When(route => !string.IsNullOrEmpty(route.DownstreamHttpVersion), () =>
|
||||
{
|
||||
RuleFor(r => r.DownstreamHttpVersion).Matches("^[0-9]([.,][0-9]{1,1})?$");
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> IsSupportedAuthenticationProviders(FileAuthenticationOptions authenticationOptions, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(authenticationOptions.AuthenticationProviderKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var schemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
|
||||
|
||||
var supportedSchemes = schemes.Select(scheme => scheme.Name).ToList();
|
||||
|
||||
return supportedSchemes.Contains(authenticationOptions.AuthenticationProviderKey);
|
||||
}
|
||||
|
||||
private static bool IsValidPeriod(FileRateLimitRule rateLimitOptions)
|
||||
{
|
||||
if (string.IsNullOrEmpty(rateLimitOptions.Period))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var period = rateLimitOptions.Period;
|
||||
|
||||
var secondsRegEx = new Regex("^[0-9]+s");
|
||||
var minutesRegEx = new Regex("^[0-9]+m");
|
||||
var hoursRegEx = new Regex("^[0-9]+h");
|
||||
var daysRegEx = new Regex("^[0-9]+d");
|
||||
|
||||
return secondsRegEx.Match(period).Success
|
||||
|| minutesRegEx.Match(period).Success
|
||||
|| hoursRegEx.Match(period).Success
|
||||
|| daysRegEx.Match(period).Success;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +1,85 @@
|
||||
namespace Ocelot.DependencyInjection
|
||||
{
|
||||
using Configuration.File;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Configuration.Memory;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
public static class ConfigurationBuilderExtensions
|
||||
{
|
||||
[Obsolete("Please set BaseUrl in ocelot.json GlobalConfiguration.BaseUrl")]
|
||||
public static IConfigurationBuilder AddOcelotBaseUrl(this IConfigurationBuilder builder, string baseUrl)
|
||||
{
|
||||
var memorySource = new MemoryConfigurationSource
|
||||
{
|
||||
InitialData = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("BaseUrl", baseUrl)
|
||||
}
|
||||
};
|
||||
|
||||
builder.Add(memorySource);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, IWebHostEnvironment env)
|
||||
{
|
||||
return builder.AddOcelot(".", env);
|
||||
}
|
||||
|
||||
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, string folder, IWebHostEnvironment env)
|
||||
{
|
||||
const string primaryConfigFile = "ocelot.json";
|
||||
|
||||
const string globalConfigFile = "ocelot.global.json";
|
||||
|
||||
const string subConfigPattern = @"^ocelot\.(.*?)\.json$";
|
||||
|
||||
string excludeConfigName = env?.EnvironmentName != null ? $"ocelot.{env.EnvironmentName}.json" : string.Empty;
|
||||
|
||||
var reg = new Regex(subConfigPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||
|
||||
var files = new DirectoryInfo(folder)
|
||||
.EnumerateFiles()
|
||||
.Where(fi => reg.IsMatch(fi.Name) && (fi.Name != excludeConfigName))
|
||||
.ToList();
|
||||
|
||||
var fileConfiguration = new FileConfiguration();
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (files.Count > 1 && file.Name.Equals(primaryConfigFile, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var lines = File.ReadAllText(file.FullName);
|
||||
|
||||
var config = JsonConvert.DeserializeObject<FileConfiguration>(lines);
|
||||
|
||||
if (file.Name.Equals(globalConfigFile, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
fileConfiguration.GlobalConfiguration = config.GlobalConfiguration;
|
||||
}
|
||||
|
||||
fileConfiguration.Aggregates.AddRange(config.Aggregates);
|
||||
fileConfiguration.ReRoutes.AddRange(config.ReRoutes);
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(fileConfiguration);
|
||||
|
||||
File.WriteAllText(primaryConfigFile, json);
|
||||
|
||||
builder.AddJsonFile(primaryConfigFile, false, false);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.DependencyInjection
|
||||
{
|
||||
using Ocelot.Configuration.File;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Configuration.Memory;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
public static class ConfigurationBuilderExtensions
|
||||
{
|
||||
[Obsolete("Please set BaseUrl in ocelot.json GlobalConfiguration.BaseUrl")]
|
||||
public static IConfigurationBuilder AddOcelotBaseUrl(this IConfigurationBuilder builder, string baseUrl)
|
||||
{
|
||||
var memorySource = new MemoryConfigurationSource
|
||||
{
|
||||
InitialData = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("BaseUrl", baseUrl)
|
||||
}
|
||||
};
|
||||
|
||||
builder.Add(memorySource);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, IWebHostEnvironment env)
|
||||
{
|
||||
return builder.AddOcelot(".", env);
|
||||
}
|
||||
|
||||
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, string folder, IWebHostEnvironment env)
|
||||
{
|
||||
const string primaryConfigFile = "ocelot.json";
|
||||
|
||||
const string globalConfigFile = "ocelot.global.json";
|
||||
|
||||
const string subConfigPattern = @"^ocelot\.(.*?)\.json$";
|
||||
|
||||
string excludeConfigName = env?.EnvironmentName != null ? $"ocelot.{env.EnvironmentName}.json" : string.Empty;
|
||||
|
||||
var reg = new Regex(subConfigPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||
|
||||
var files = new DirectoryInfo(folder)
|
||||
.EnumerateFiles()
|
||||
.Where(fi => reg.IsMatch(fi.Name) && (fi.Name != excludeConfigName))
|
||||
.ToList();
|
||||
|
||||
var fileConfiguration = new FileConfiguration();
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (files.Count > 1 && file.Name.Equals(primaryConfigFile, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var lines = File.ReadAllText(file.FullName);
|
||||
|
||||
var config = JsonConvert.DeserializeObject<FileConfiguration>(lines);
|
||||
|
||||
if (file.Name.Equals(globalConfigFile, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
fileConfiguration.GlobalConfiguration = config.GlobalConfiguration;
|
||||
}
|
||||
|
||||
fileConfiguration.Aggregates.AddRange(config.Aggregates);
|
||||
fileConfiguration.Routes.AddRange(config.Routes);
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(fileConfiguration);
|
||||
|
||||
File.WriteAllText(primaryConfigFile, json);
|
||||
|
||||
builder.AddJsonFile(primaryConfigFile, false, false);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,11 @@ namespace Ocelot.DependencyInjection
|
||||
where T : ILoadBalancer;
|
||||
|
||||
IOcelotBuilder AddCustomLoadBalancer<T>(
|
||||
Func<DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
Func<DownstreamRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer;
|
||||
|
||||
IOcelotBuilder AddCustomLoadBalancer<T>(
|
||||
Func<IServiceProvider, DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
Func<IServiceProvider, DownstreamRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer;
|
||||
|
||||
IOcelotBuilder AddConfigPlaceholders();
|
||||
|
@ -65,13 +65,13 @@ namespace Ocelot.DependencyInjection
|
||||
Services.TryAddSingleton<IInternalConfigurationRepository, InMemoryInternalConfigurationRepository>();
|
||||
Services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>();
|
||||
Services.TryAddSingleton<HostAndPortValidator>();
|
||||
Services.TryAddSingleton<IReRoutesCreator, ReRoutesCreator>();
|
||||
Services.TryAddSingleton<IRoutesCreator, RoutesCreator>();
|
||||
Services.TryAddSingleton<IAggregatesCreator, AggregatesCreator>();
|
||||
Services.TryAddSingleton<IReRouteKeyCreator, ReRouteKeyCreator>();
|
||||
Services.TryAddSingleton<IRouteKeyCreator, RouteKeyCreator>();
|
||||
Services.TryAddSingleton<IConfigurationCreator, ConfigurationCreator>();
|
||||
Services.TryAddSingleton<IDynamicsCreator, DynamicsCreator>();
|
||||
Services.TryAddSingleton<ILoadBalancerOptionsCreator, LoadBalancerOptionsCreator>();
|
||||
Services.TryAddSingleton<ReRouteFluentValidator>();
|
||||
Services.TryAddSingleton<RouteFluentValidator>();
|
||||
Services.TryAddSingleton<FileGlobalConfigurationFluentValidator>();
|
||||
Services.TryAddSingleton<FileQoSOptionsFluentValidator>();
|
||||
Services.TryAddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>();
|
||||
@ -80,7 +80,7 @@ namespace Ocelot.DependencyInjection
|
||||
Services.TryAddSingleton<IRequestIdKeyCreator, RequestIdKeyCreator>();
|
||||
Services.TryAddSingleton<IServiceProviderConfigurationCreator, ServiceProviderConfigurationCreator>();
|
||||
Services.TryAddSingleton<IQoSOptionsCreator, QoSOptionsCreator>();
|
||||
Services.TryAddSingleton<IReRouteOptionsCreator, ReRouteOptionsCreator>();
|
||||
Services.TryAddSingleton<IRouteOptionsCreator, RouteOptionsCreator>();
|
||||
Services.TryAddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>();
|
||||
Services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>();
|
||||
Services.TryAddSingleton<IRegionCreator, RegionCreator>();
|
||||
@ -175,14 +175,14 @@ namespace Ocelot.DependencyInjection
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>()
|
||||
where T : ILoadBalancer, new()
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) => new T());
|
||||
AddCustomLoadBalancer((provider, route, serviceDiscoveryProvider) => new T());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) =>
|
||||
AddCustomLoadBalancer((provider, route, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc());
|
||||
return this;
|
||||
}
|
||||
@ -190,26 +190,26 @@ namespace Ocelot.DependencyInjection
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<IServiceProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) =>
|
||||
AddCustomLoadBalancer((provider, route, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(provider));
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<DownstreamRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(reRoute, serviceDiscoveryProvider));
|
||||
AddCustomLoadBalancer((provider, route, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(route, serviceDiscoveryProvider));
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<IServiceProvider, DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<IServiceProvider, DownstreamRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
Services.AddSingleton<ILoadBalancerCreator>(provider =>
|
||||
new DelegateInvokingLoadBalancerCreator<T>(
|
||||
(reRoute, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(provider, reRoute, serviceDiscoveryProvider)));
|
||||
(route, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(provider, route, serviceDiscoveryProvider)));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
using Ocelot.Logging;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.PathManipulation;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
using Ocelot.PathManipulation;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class ClaimsToDownstreamPathMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
@ -24,16 +24,16 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (downstreamReRoute.ClaimsToPath.Any())
|
||||
if (downstreamRoute.ClaimsToPath.Any())
|
||||
{
|
||||
Logger.LogInformation($"{downstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to path");
|
||||
|
||||
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} has instructions to convert claims to path");
|
||||
|
||||
var templatePlaceholderNameAndValues = httpContext.Items.TemplatePlaceholderNameAndValues();
|
||||
|
||||
var response = _changeDownstreamPathTemplate.ChangeDownstreamPath(downstreamReRoute.ClaimsToPath, httpContext.User.Claims,
|
||||
downstreamReRoute.DownstreamPathTemplate, templatePlaceholderNameAndValues);
|
||||
|
||||
var response = _changeDownstreamPathTemplate.ChangeDownstreamPath(downstreamRoute.ClaimsToPath, httpContext.User.Claims,
|
||||
downstreamRoute.DownstreamPathTemplate, templatePlaceholderNameAndValues);
|
||||
|
||||
if (response.IsError)
|
||||
{
|
||||
|
@ -4,19 +4,19 @@
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class DownstreamRoute
|
||||
public class DownstreamRouteHolder
|
||||
{
|
||||
public DownstreamRoute()
|
||||
public DownstreamRouteHolder()
|
||||
{
|
||||
}
|
||||
|
||||
public DownstreamRoute(List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, ReRoute reRoute)
|
||||
public DownstreamRouteHolder(List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, Route route)
|
||||
{
|
||||
TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues;
|
||||
ReRoute = reRoute;
|
||||
Route = route;
|
||||
}
|
||||
|
||||
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; private set; }
|
||||
public ReRoute ReRoute { get; private set; }
|
||||
public Route Route { get; private set; }
|
||||
}
|
||||
}
|
@ -1,140 +1,139 @@
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using System;
|
||||
using Configuration;
|
||||
using Configuration.Builder;
|
||||
using Configuration.Creator;
|
||||
using LoadBalancer.LoadBalancers;
|
||||
using Responses;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UrlMatcher;
|
||||
|
||||
public class DownstreamRouteCreator : IDownstreamRouteProvider
|
||||
{
|
||||
private readonly IQoSOptionsCreator _qoSOptionsCreator;
|
||||
private readonly ConcurrentDictionary<string, OkResponse<DownstreamRoute>> _cache;
|
||||
|
||||
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
|
||||
{
|
||||
_qoSOptionsCreator = qoSOptionsCreator;
|
||||
_cache = new ConcurrentDictionary<string, OkResponse<DownstreamRoute>>();
|
||||
}
|
||||
|
||||
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamQueryString, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
{
|
||||
var serviceName = GetServiceName(upstreamUrlPath);
|
||||
|
||||
var downstreamPath = GetDownstreamPath(upstreamUrlPath);
|
||||
|
||||
if (HasQueryString(downstreamPath))
|
||||
{
|
||||
downstreamPath = RemoveQueryString(downstreamPath);
|
||||
}
|
||||
|
||||
var downstreamPathForKeys = $"/{serviceName}{downstreamPath}";
|
||||
|
||||
var loadBalancerKey = CreateLoadBalancerKey(downstreamPathForKeys, upstreamHttpMethod, configuration.LoadBalancerOptions);
|
||||
|
||||
if (_cache.TryGetValue(loadBalancerKey, out var downstreamRoute))
|
||||
{
|
||||
return downstreamRoute;
|
||||
}
|
||||
|
||||
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new List<string> { upstreamHttpMethod });
|
||||
|
||||
var upstreamPathTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue(upstreamUrlPath).Build();
|
||||
|
||||
var downstreamReRouteBuilder = new DownstreamReRouteBuilder()
|
||||
.WithServiceName(serviceName)
|
||||
.WithLoadBalancerKey(loadBalancerKey)
|
||||
.WithDownstreamPathTemplate(downstreamPath)
|
||||
.WithUseServiceDiscovery(true)
|
||||
.WithHttpHandlerOptions(configuration.HttpHandlerOptions)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithDownstreamScheme(configuration.DownstreamScheme)
|
||||
.WithLoadBalancerOptions(configuration.LoadBalancerOptions)
|
||||
.WithDownstreamHttpVersion(configuration.DownstreamHttpVersion)
|
||||
.WithUpstreamPathTemplate(upstreamPathTemplate);
|
||||
|
||||
var rateLimitOptions = configuration.ReRoutes != null
|
||||
? configuration.ReRoutes
|
||||
.SelectMany(x => x.DownstreamReRoute)
|
||||
.FirstOrDefault(x => x.ServiceName == serviceName)
|
||||
: null;
|
||||
|
||||
if (rateLimitOptions != null)
|
||||
{
|
||||
downstreamReRouteBuilder
|
||||
.WithRateLimitOptions(rateLimitOptions.RateLimitOptions)
|
||||
.WithEnableRateLimiting(true);
|
||||
}
|
||||
|
||||
var downstreamReRoute = downstreamReRouteBuilder.Build();
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string>() { upstreamHttpMethod })
|
||||
.WithUpstreamPathTemplate(upstreamPathTemplate)
|
||||
.Build();
|
||||
|
||||
downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
||||
|
||||
_cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute);
|
||||
|
||||
return downstreamRoute;
|
||||
}
|
||||
|
||||
private static string RemoveQueryString(string downstreamPath)
|
||||
{
|
||||
return downstreamPath
|
||||
.Substring(0, downstreamPath.IndexOf('?'));
|
||||
}
|
||||
|
||||
private static bool HasQueryString(string downstreamPath)
|
||||
{
|
||||
return downstreamPath.Contains("?");
|
||||
}
|
||||
|
||||
private static string GetDownstreamPath(string upstreamUrlPath)
|
||||
{
|
||||
if (upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
return upstreamUrlPath
|
||||
.Substring(upstreamUrlPath.IndexOf('/', 1));
|
||||
}
|
||||
|
||||
private static string GetServiceName(string upstreamUrlPath)
|
||||
{
|
||||
if (upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||
{
|
||||
return upstreamUrlPath
|
||||
.Substring(1);
|
||||
}
|
||||
|
||||
return upstreamUrlPath
|
||||
.Substring(1, upstreamUrlPath.IndexOf('/', 1))
|
||||
.TrimEnd('/');
|
||||
}
|
||||
|
||||
private string CreateLoadBalancerKey(string downstreamTemplatePath, string httpMethod, LoadBalancerOptions loadBalancerOptions)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(loadBalancerOptions.Type) && !string.IsNullOrEmpty(loadBalancerOptions.Key) && loadBalancerOptions.Type == nameof(CookieStickySessions))
|
||||
{
|
||||
return $"{nameof(CookieStickySessions)}:{loadBalancerOptions.Key}";
|
||||
}
|
||||
|
||||
return CreateQoSKey(downstreamTemplatePath, httpMethod);
|
||||
}
|
||||
|
||||
private string CreateQoSKey(string downstreamTemplatePath, string httpMethod)
|
||||
{
|
||||
var loadBalancerKey = $"{downstreamTemplatePath}|{httpMethod}";
|
||||
return loadBalancerKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
|
||||
public class DownstreamRouteCreator : IDownstreamRouteProvider
|
||||
{
|
||||
private readonly IQoSOptionsCreator _qoSOptionsCreator;
|
||||
private readonly ConcurrentDictionary<string, OkResponse<DownstreamRouteHolder>> _cache;
|
||||
|
||||
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
|
||||
{
|
||||
_qoSOptionsCreator = qoSOptionsCreator;
|
||||
_cache = new ConcurrentDictionary<string, OkResponse<DownstreamRouteHolder>>();
|
||||
}
|
||||
|
||||
public Response<DownstreamRouteHolder> Get(string upstreamUrlPath, string upstreamQueryString, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
{
|
||||
var serviceName = GetServiceName(upstreamUrlPath);
|
||||
|
||||
var downstreamPath = GetDownstreamPath(upstreamUrlPath);
|
||||
|
||||
if (HasQueryString(downstreamPath))
|
||||
{
|
||||
downstreamPath = RemoveQueryString(downstreamPath);
|
||||
}
|
||||
|
||||
var downstreamPathForKeys = $"/{serviceName}{downstreamPath}";
|
||||
|
||||
var loadBalancerKey = CreateLoadBalancerKey(downstreamPathForKeys, upstreamHttpMethod, configuration.LoadBalancerOptions);
|
||||
|
||||
if (_cache.TryGetValue(loadBalancerKey, out var downstreamRouteHolder))
|
||||
{
|
||||
return downstreamRouteHolder;
|
||||
}
|
||||
|
||||
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new List<string> { upstreamHttpMethod });
|
||||
|
||||
var upstreamPathTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue(upstreamUrlPath).Build();
|
||||
|
||||
var downstreamRouteBuilder = new DownstreamRouteBuilder()
|
||||
.WithServiceName(serviceName)
|
||||
.WithLoadBalancerKey(loadBalancerKey)
|
||||
.WithDownstreamPathTemplate(downstreamPath)
|
||||
.WithUseServiceDiscovery(true)
|
||||
.WithHttpHandlerOptions(configuration.HttpHandlerOptions)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithDownstreamScheme(configuration.DownstreamScheme)
|
||||
.WithLoadBalancerOptions(configuration.LoadBalancerOptions)
|
||||
.WithDownstreamHttpVersion(configuration.DownstreamHttpVersion)
|
||||
.WithUpstreamPathTemplate(upstreamPathTemplate);
|
||||
|
||||
var rateLimitOptions = configuration.Routes != null
|
||||
? configuration.Routes
|
||||
.SelectMany(x => x.DownstreamRoute)
|
||||
.FirstOrDefault(x => x.ServiceName == serviceName)
|
||||
: null;
|
||||
|
||||
if (rateLimitOptions != null)
|
||||
{
|
||||
downstreamRouteBuilder
|
||||
.WithRateLimitOptions(rateLimitOptions.RateLimitOptions)
|
||||
.WithEnableRateLimiting(true);
|
||||
}
|
||||
|
||||
var downstreamRoute = downstreamRouteBuilder.Build();
|
||||
|
||||
var route = new RouteBuilder()
|
||||
.WithDownstreamRoute(downstreamRoute)
|
||||
.WithUpstreamHttpMethod(new List<string>() { upstreamHttpMethod })
|
||||
.WithUpstreamPathTemplate(upstreamPathTemplate)
|
||||
.Build();
|
||||
|
||||
downstreamRouteHolder = new OkResponse<DownstreamRouteHolder>(new DownstreamRouteHolder(new List<PlaceholderNameAndValue>(), route));
|
||||
|
||||
_cache.AddOrUpdate(loadBalancerKey, downstreamRouteHolder, (x, y) => downstreamRouteHolder);
|
||||
|
||||
return downstreamRouteHolder;
|
||||
}
|
||||
|
||||
private static string RemoveQueryString(string downstreamPath)
|
||||
{
|
||||
return downstreamPath
|
||||
.Substring(0, downstreamPath.IndexOf('?'));
|
||||
}
|
||||
|
||||
private static bool HasQueryString(string downstreamPath)
|
||||
{
|
||||
return downstreamPath.Contains("?");
|
||||
}
|
||||
|
||||
private static string GetDownstreamPath(string upstreamUrlPath)
|
||||
{
|
||||
if (upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
return upstreamUrlPath
|
||||
.Substring(upstreamUrlPath.IndexOf('/', 1));
|
||||
}
|
||||
|
||||
private static string GetServiceName(string upstreamUrlPath)
|
||||
{
|
||||
if (upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||
{
|
||||
return upstreamUrlPath
|
||||
.Substring(1);
|
||||
}
|
||||
|
||||
return upstreamUrlPath
|
||||
.Substring(1, upstreamUrlPath.IndexOf('/', 1))
|
||||
.TrimEnd('/');
|
||||
}
|
||||
|
||||
private string CreateLoadBalancerKey(string downstreamTemplatePath, string httpMethod, LoadBalancerOptions loadBalancerOptions)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(loadBalancerOptions.Type) && !string.IsNullOrEmpty(loadBalancerOptions.Key) && loadBalancerOptions.Type == nameof(CookieStickySessions))
|
||||
{
|
||||
return $"{nameof(CookieStickySessions)}:{loadBalancerOptions.Key}";
|
||||
}
|
||||
|
||||
return CreateQoSKey(downstreamTemplatePath, httpMethod);
|
||||
}
|
||||
|
||||
private string CreateQoSKey(string downstreamTemplatePath, string httpMethod)
|
||||
{
|
||||
var loadBalancerKey = $"{downstreamTemplatePath}|{httpMethod}";
|
||||
return loadBalancerKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +1,62 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public class DownstreamRouteFinder : IDownstreamRouteProvider
|
||||
{
|
||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
|
||||
|
||||
public DownstreamRouteFinder(IUrlPathToUrlTemplateMatcher urlMatcher, IPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder)
|
||||
{
|
||||
_urlMatcher = urlMatcher;
|
||||
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
|
||||
}
|
||||
|
||||
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamQueryString, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
{
|
||||
var downstreamRoutes = new List<DownstreamRoute>();
|
||||
|
||||
var applicableReRoutes = configuration.ReRoutes
|
||||
.Where(r => RouteIsApplicableToThisRequest(r, httpMethod, upstreamHost))
|
||||
.OrderByDescending(x => x.UpstreamTemplatePattern.Priority);
|
||||
|
||||
foreach (var reRoute in applicableReRoutes)
|
||||
{
|
||||
var urlMatch = _urlMatcher.Match(upstreamUrlPath, upstreamQueryString, reRoute.UpstreamTemplatePattern);
|
||||
|
||||
if (urlMatch.Data.Match)
|
||||
{
|
||||
downstreamRoutes.Add(GetPlaceholderNamesAndValues(upstreamUrlPath, upstreamQueryString, reRoute));
|
||||
}
|
||||
}
|
||||
|
||||
if (downstreamRoutes.Any())
|
||||
{
|
||||
var notNullOption = downstreamRoutes.FirstOrDefault(x => !string.IsNullOrEmpty(x.ReRoute.UpstreamHost));
|
||||
var nullOption = downstreamRoutes.FirstOrDefault(x => string.IsNullOrEmpty(x.ReRoute.UpstreamHost));
|
||||
|
||||
return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
|
||||
}
|
||||
|
||||
return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(upstreamUrlPath, httpMethod));
|
||||
}
|
||||
|
||||
private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
|
||||
{
|
||||
return (reRoute.UpstreamHttpMethod.Count == 0 || reRoute.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(httpMethod.ToLower())) &&
|
||||
(string.IsNullOrEmpty(reRoute.UpstreamHost) || reRoute.UpstreamHost == upstreamHost);
|
||||
}
|
||||
|
||||
private DownstreamRoute GetPlaceholderNamesAndValues(string path, string query, ReRoute reRoute)
|
||||
{
|
||||
var templatePlaceholderNameAndValues = _placeholderNameAndValueFinder.Find(path, query, reRoute.UpstreamTemplatePattern.OriginalValue);
|
||||
|
||||
return new DownstreamRoute(templatePlaceholderNameAndValues.Data, reRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public class DownstreamRouteFinder : IDownstreamRouteProvider
|
||||
{
|
||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
|
||||
|
||||
public DownstreamRouteFinder(IUrlPathToUrlTemplateMatcher urlMatcher, IPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder)
|
||||
{
|
||||
_urlMatcher = urlMatcher;
|
||||
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
|
||||
}
|
||||
|
||||
public Response<DownstreamRouteHolder> Get(string upstreamUrlPath, string upstreamQueryString, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
{
|
||||
var downstreamRoutes = new List<DownstreamRouteHolder>();
|
||||
|
||||
var applicableRoutes = configuration.Routes
|
||||
.Where(r => RouteIsApplicableToThisRequest(r, httpMethod, upstreamHost))
|
||||
.OrderByDescending(x => x.UpstreamTemplatePattern.Priority);
|
||||
|
||||
foreach (var route in applicableRoutes)
|
||||
{
|
||||
var urlMatch = _urlMatcher.Match(upstreamUrlPath, upstreamQueryString, route.UpstreamTemplatePattern);
|
||||
|
||||
if (urlMatch.Data.Match)
|
||||
{
|
||||
downstreamRoutes.Add(GetPlaceholderNamesAndValues(upstreamUrlPath, upstreamQueryString, route));
|
||||
}
|
||||
}
|
||||
|
||||
if (downstreamRoutes.Any())
|
||||
{
|
||||
var notNullOption = downstreamRoutes.FirstOrDefault(x => !string.IsNullOrEmpty(x.Route.UpstreamHost));
|
||||
var nullOption = downstreamRoutes.FirstOrDefault(x => string.IsNullOrEmpty(x.Route.UpstreamHost));
|
||||
|
||||
return notNullOption != null ? new OkResponse<DownstreamRouteHolder>(notNullOption) : new OkResponse<DownstreamRouteHolder>(nullOption);
|
||||
}
|
||||
|
||||
return new ErrorResponse<DownstreamRouteHolder>(new UnableToFindDownstreamRouteError(upstreamUrlPath, httpMethod));
|
||||
}
|
||||
|
||||
private bool RouteIsApplicableToThisRequest(Route route, string httpMethod, string upstreamHost)
|
||||
{
|
||||
return (route.UpstreamHttpMethod.Count == 0 || route.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(httpMethod.ToLower())) &&
|
||||
(string.IsNullOrEmpty(route.UpstreamHost) || route.UpstreamHost == upstreamHost);
|
||||
}
|
||||
|
||||
private DownstreamRouteHolder GetPlaceholderNamesAndValues(string path, string query, Route route)
|
||||
{
|
||||
var templatePlaceholderNameAndValues = _placeholderNameAndValueFinder.Find(path, query, route.UpstreamTemplatePattern.OriginalValue);
|
||||
|
||||
return new DownstreamRouteHolder(templatePlaceholderNameAndValues.Data, route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,44 @@
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class DownstreamRouteProviderFactory : IDownstreamRouteProviderFactory
|
||||
{
|
||||
private readonly Dictionary<string, IDownstreamRouteProvider> _providers;
|
||||
private readonly IOcelotLogger _logger;
|
||||
|
||||
public DownstreamRouteProviderFactory(IServiceProvider provider, IOcelotLoggerFactory factory)
|
||||
{
|
||||
_logger = factory.CreateLogger<DownstreamRouteProviderFactory>();
|
||||
_providers = provider.GetServices<IDownstreamRouteProvider>().ToDictionary(x => x.GetType().Name);
|
||||
}
|
||||
|
||||
public IDownstreamRouteProvider Get(IInternalConfiguration config)
|
||||
{
|
||||
//todo - this is a bit hacky we are saying there are no reRoutes or there are reRoutes but none of them have
|
||||
//an upstream path template which means they are dyanmic and service discovery is on...
|
||||
if ((!config.ReRoutes.Any() || config.ReRoutes.All(x => string.IsNullOrEmpty(x.UpstreamTemplatePattern?.OriginalValue))) && IsServiceDiscovery(config.ServiceProviderConfiguration))
|
||||
{
|
||||
_logger.LogInformation($"Selected {nameof(DownstreamRouteCreator)} as DownstreamRouteProvider for this request");
|
||||
return _providers[nameof(DownstreamRouteCreator)];
|
||||
}
|
||||
|
||||
return _providers[nameof(DownstreamRouteFinder)];
|
||||
}
|
||||
|
||||
private bool IsServiceDiscovery(ServiceProviderConfiguration config)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(config?.Host) && config?.Port > 0 && !string.IsNullOrEmpty(config.Type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class DownstreamRouteProviderFactory : IDownstreamRouteProviderFactory
|
||||
{
|
||||
private readonly Dictionary<string, IDownstreamRouteProvider> _providers;
|
||||
private readonly IOcelotLogger _logger;
|
||||
|
||||
public DownstreamRouteProviderFactory(IServiceProvider provider, IOcelotLoggerFactory factory)
|
||||
{
|
||||
_logger = factory.CreateLogger<DownstreamRouteProviderFactory>();
|
||||
_providers = provider.GetServices<IDownstreamRouteProvider>().ToDictionary(x => x.GetType().Name);
|
||||
}
|
||||
|
||||
public IDownstreamRouteProvider Get(IInternalConfiguration config)
|
||||
{
|
||||
//todo - this is a bit hacky we are saying there are no routes or there are routes but none of them have
|
||||
//an upstream path template which means they are dyanmic and service discovery is on...
|
||||
if ((!config.Routes.Any() || config.Routes.All(x => string.IsNullOrEmpty(x.UpstreamTemplatePattern?.OriginalValue))) && IsServiceDiscovery(config.ServiceProviderConfiguration))
|
||||
{
|
||||
_logger.LogInformation($"Selected {nameof(DownstreamRouteCreator)} as DownstreamRouteProvider for this request");
|
||||
return _providers[nameof(DownstreamRouteCreator)];
|
||||
}
|
||||
|
||||
return _providers[nameof(DownstreamRouteFinder)];
|
||||
}
|
||||
|
||||
private bool IsServiceDiscovery(ServiceProviderConfiguration config)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(config?.Host) && config?.Port > 0 && !string.IsNullOrEmpty(config.Type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public interface IDownstreamRouteProvider
|
||||
{
|
||||
Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamQueryString, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public interface IDownstreamRouteProvider
|
||||
{
|
||||
Response<DownstreamRouteHolder> Get(string upstreamUrlPath, string upstreamQueryString, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
public class UnableToFindDownstreamRouteError : Error
|
||||
{
|
||||
public UnableToFindDownstreamRouteError(string path, string httpVerb)
|
||||
: base($"Failed to match ReRoute configuration for upstream path: {path}, verb: {httpVerb}.", OcelotErrorCode.UnableToFindDownstreamRouteError, 404)
|
||||
: base($"Failed to match Route configuration for upstream path: {path}, verb: {httpVerb}.", OcelotErrorCode.UnableToFindDownstreamRouteError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamPathTemplates = string.Join(", ", response.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));
|
||||
var downstreamPathTemplates = string.Join(", ", response.Data.Route.DownstreamRoute.Select(r => r.DownstreamPathTemplate.Value));
|
||||
Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");
|
||||
|
||||
// why set both of these on HttpContext
|
||||
|
@ -12,9 +12,9 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class DownstreamUrlCreatorMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
@ -32,15 +32,15 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
var templatePlaceholderNameAndValues = httpContext.Items.TemplatePlaceholderNameAndValues();
|
||||
|
||||
var response = _replacer
|
||||
.Replace(downstreamReRoute.DownstreamPathTemplate.Value, templatePlaceholderNameAndValues);
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
.Replace(downstreamRoute.DownstreamPathTemplate.Value, templatePlaceholderNameAndValues);
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
if (response.IsError)
|
||||
{
|
||||
Logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
|
||||
@ -49,19 +49,19 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(downstreamReRoute.DownstreamScheme))
|
||||
{
|
||||
//todo make sure this works, hopefully there is a test ;E
|
||||
httpContext.Items.DownstreamRequest().Scheme = downstreamReRoute.DownstreamScheme;
|
||||
}
|
||||
|
||||
var internalConfiguration = httpContext.Items.IInternalConfiguration();
|
||||
|
||||
if (ServiceFabricRequest(internalConfiguration, downstreamReRoute))
|
||||
{
|
||||
var pathAndQuery = CreateServiceFabricUri(downstreamRequest, downstreamReRoute, templatePlaceholderNameAndValues, response);
|
||||
|
||||
//todo check this works again hope there is a test..
|
||||
if (!string.IsNullOrEmpty(downstreamRoute.DownstreamScheme))
|
||||
{
|
||||
//todo make sure this works, hopefully there is a test ;E
|
||||
httpContext.Items.DownstreamRequest().Scheme = downstreamRoute.DownstreamScheme;
|
||||
}
|
||||
|
||||
var internalConfiguration = httpContext.Items.IInternalConfiguration();
|
||||
|
||||
if (ServiceFabricRequest(internalConfiguration, downstreamRoute))
|
||||
{
|
||||
var pathAndQuery = CreateServiceFabricUri(downstreamRequest, downstreamRoute, templatePlaceholderNameAndValues, response);
|
||||
|
||||
//todo check this works again hope there is a test..
|
||||
downstreamRequest.AbsolutePath = pathAndQuery.path;
|
||||
downstreamRequest.Query = pathAndQuery.query;
|
||||
}
|
||||
@ -70,7 +70,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
var dsPath = response.Data;
|
||||
|
||||
if (ContainsQueryString(dsPath))
|
||||
{
|
||||
{
|
||||
downstreamRequest.AbsolutePath = GetPath(dsPath);
|
||||
|
||||
if (string.IsNullOrEmpty(downstreamRequest.Query))
|
||||
@ -83,7 +83,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
RemoveQueryStringParametersThatHaveBeenUsedInTemplate(downstreamRequest, templatePlaceholderNameAndValues);
|
||||
|
||||
downstreamRequest.AbsolutePath = dsPath.Value;
|
||||
@ -133,17 +133,17 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
return dsPath.Value.Contains("?");
|
||||
}
|
||||
|
||||
private (string path, string query) CreateServiceFabricUri(DownstreamRequest downstreamRequest, DownstreamReRoute downstreamReRoute, List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, Response<DownstreamPath> dsPath)
|
||||
private (string path, string query) CreateServiceFabricUri(DownstreamRequest downstreamRequest, DownstreamRoute downstreamRoute, List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, Response<DownstreamPath> dsPath)
|
||||
{
|
||||
var query = downstreamRequest.Query;
|
||||
var serviceName = _replacer.Replace(downstreamReRoute.ServiceName, templatePlaceholderNameAndValues);
|
||||
var serviceName = _replacer.Replace(downstreamRoute.ServiceName, templatePlaceholderNameAndValues);
|
||||
var pathTemplate = $"/{serviceName.Data.Value}{dsPath.Data.Value}";
|
||||
return (pathTemplate, query);
|
||||
}
|
||||
|
||||
private static bool ServiceFabricRequest(IInternalConfiguration config, DownstreamReRoute downstreamReRoute)
|
||||
private static bool ServiceFabricRequest(IInternalConfiguration config, DownstreamRoute downstreamRoute)
|
||||
{
|
||||
return config.ServiceProviderConfiguration.Type?.ToLower() == "servicefabric" && downstreamReRoute.UseServiceDiscovery;
|
||||
return config.ServiceProviderConfiguration.Type?.ToLower() == "servicefabric" && downstreamRoute.UseServiceDiscovery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace Ocelot.Headers.Middleware
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System.Linq;
|
||||
@ -23,15 +23,15 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (downstreamReRoute.ClaimsToHeaders.Any())
|
||||
if (downstreamRoute.ClaimsToHeaders.Any())
|
||||
{
|
||||
Logger.LogInformation($"{downstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
|
||||
|
||||
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(downstreamReRoute.ClaimsToHeaders, httpContext.User.Claims, downstreamRequest);
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(downstreamRoute.ClaimsToHeaders, httpContext.User.Claims, downstreamRequest);
|
||||
|
||||
if (response.IsError)
|
||||
{
|
||||
|
@ -32,14 +32,14 @@ namespace Ocelot.Headers.Middleware
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
var preFAndRs = downstreamReRoute.UpstreamHeadersFindAndReplace;
|
||||
var preFAndRs = downstreamRoute.UpstreamHeadersFindAndReplace;
|
||||
|
||||
//todo - this should be on httprequestmessage not httpcontext?
|
||||
_preReplacer.Replace(httpContext, preFAndRs);
|
||||
|
||||
_addHeadersToRequest.SetHeadersOnDownstreamRequest(downstreamReRoute.AddHeadersToUpstream, httpContext);
|
||||
_addHeadersToRequest.SetHeadersOnDownstreamRequest(downstreamRoute.AddHeadersToUpstream, httpContext);
|
||||
|
||||
await _next.Invoke(httpContext);
|
||||
|
||||
@ -50,13 +50,13 @@ namespace Ocelot.Headers.Middleware
|
||||
return;
|
||||
}
|
||||
|
||||
var postFAndRs = downstreamReRoute.DownstreamHeadersFindAndReplace;
|
||||
var postFAndRs = downstreamRoute.DownstreamHeadersFindAndReplace;
|
||||
|
||||
_postReplacer.Replace(httpContext, postFAndRs);
|
||||
|
||||
var downstreamResponse = httpContext.Items.DownstreamResponse();
|
||||
|
||||
_addHeadersToResponse.Add(downstreamReRoute.AddHeadersToDownstream, downstreamResponse);
|
||||
_addHeadersToResponse.Add(downstreamRoute.AddHeadersToDownstream, downstreamResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class CookieStickySessionsCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
var loadBalancer = new RoundRobin(async () => await serviceProvider.Get());
|
||||
var bus = new InMemoryBus<StickySession>();
|
||||
return new OkResponse<ILoadBalancer>(new CookieStickySessions(loadBalancer, reRoute.LoadBalancerOptions.Key,
|
||||
reRoute.LoadBalancerOptions.ExpiryInMs, bus));
|
||||
}
|
||||
|
||||
public string Type => nameof(CookieStickySessions);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class CookieStickySessionsCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
var loadBalancer = new RoundRobin(async () => await serviceProvider.Get());
|
||||
var bus = new InMemoryBus<StickySession>();
|
||||
return new OkResponse<ILoadBalancer>(new CookieStickySessions(loadBalancer, route.LoadBalancerOptions.Key,
|
||||
route.LoadBalancerOptions.ExpiryInMs, bus));
|
||||
}
|
||||
|
||||
public string Type => nameof(CookieStickySessions);
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class DelegateInvokingLoadBalancerCreator<T> : ILoadBalancerCreator
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
private readonly Func<DownstreamReRoute, IServiceDiscoveryProvider, ILoadBalancer> _creatorFunc;
|
||||
|
||||
public DelegateInvokingLoadBalancerCreator(
|
||||
Func<DownstreamReRoute, IServiceDiscoveryProvider, ILoadBalancer> creatorFunc)
|
||||
{
|
||||
_creatorFunc = creatorFunc;
|
||||
}
|
||||
|
||||
public Response<ILoadBalancer> Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(_creatorFunc(reRoute, serviceProvider));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(new ErrorInvokingLoadBalancerCreator(e));
|
||||
}
|
||||
}
|
||||
|
||||
public string Type => typeof(T).Name;
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class DelegateInvokingLoadBalancerCreator<T> : ILoadBalancerCreator
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
private readonly Func<DownstreamRoute, IServiceDiscoveryProvider, ILoadBalancer> _creatorFunc;
|
||||
|
||||
public DelegateInvokingLoadBalancerCreator(
|
||||
Func<DownstreamRoute, IServiceDiscoveryProvider, ILoadBalancer> creatorFunc)
|
||||
{
|
||||
_creatorFunc = creatorFunc;
|
||||
}
|
||||
|
||||
public Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(_creatorFunc(route, serviceProvider));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(new ErrorInvokingLoadBalancerCreator(e));
|
||||
}
|
||||
}
|
||||
|
||||
public string Type => typeof(T).Name;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public interface ILoadBalancerCreator
|
||||
{
|
||||
Response<ILoadBalancer> Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider);
|
||||
string Type { get; }
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public interface ILoadBalancerCreator
|
||||
{
|
||||
Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryProvider serviceProvider);
|
||||
string Type { get; }
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public interface ILoadBalancerFactory
|
||||
{
|
||||
Response<ILoadBalancer> Get(DownstreamReRoute reRoute, ServiceProviderConfiguration config);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public interface ILoadBalancerFactory
|
||||
{
|
||||
Response<ILoadBalancer> Get(DownstreamRoute route, ServiceProviderConfiguration config);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
public interface ILoadBalancerHouse
|
||||
{
|
||||
Response<ILoadBalancer> Get(DownstreamReRoute reRoute, ServiceProviderConfiguration config);
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
public interface ILoadBalancerHouse
|
||||
{
|
||||
Response<ILoadBalancer> Get(DownstreamRoute route, ServiceProviderConfiguration config);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class LeastConnectionCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(new LeastConnection(async () => await serviceProvider.Get(), reRoute.ServiceName));
|
||||
}
|
||||
|
||||
public string Type => nameof(LeastConnection);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class LeastConnectionCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(new LeastConnection(async () => await serviceProvider.Get(), route.ServiceName));
|
||||
}
|
||||
|
||||
public string Type => nameof(LeastConnection);
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,48 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
|
||||
public class LoadBalancerFactory : ILoadBalancerFactory
|
||||
{
|
||||
private readonly IServiceDiscoveryProviderFactory _serviceProviderFactory;
|
||||
private readonly IEnumerable<ILoadBalancerCreator> _loadBalancerCreators;
|
||||
|
||||
public LoadBalancerFactory(IServiceDiscoveryProviderFactory serviceProviderFactory, IEnumerable<ILoadBalancerCreator> loadBalancerCreators)
|
||||
{
|
||||
_serviceProviderFactory = serviceProviderFactory;
|
||||
_loadBalancerCreators = loadBalancerCreators;
|
||||
}
|
||||
|
||||
public Response<ILoadBalancer> Get(DownstreamReRoute reRoute, ServiceProviderConfiguration config)
|
||||
{
|
||||
var serviceProviderFactoryResponse = _serviceProviderFactory.Get(config, reRoute);
|
||||
|
||||
if (serviceProviderFactoryResponse.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(serviceProviderFactoryResponse.Errors);
|
||||
}
|
||||
|
||||
var serviceProvider = serviceProviderFactoryResponse.Data;
|
||||
var requestedType = reRoute.LoadBalancerOptions?.Type ?? nameof(NoLoadBalancer);
|
||||
var applicableCreator = _loadBalancerCreators.SingleOrDefault(c => c.Type == requestedType);
|
||||
|
||||
if (applicableCreator == null)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(new CouldNotFindLoadBalancerCreator($"Could not find load balancer creator for Type: {requestedType}, please check your config specified the correct load balancer and that you have registered a class with the same name."));
|
||||
}
|
||||
|
||||
var createdLoadBalancerResponse = applicableCreator.Create(reRoute, serviceProvider);
|
||||
|
||||
if (createdLoadBalancerResponse.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(createdLoadBalancerResponse.Errors);
|
||||
}
|
||||
|
||||
return new OkResponse<ILoadBalancer>(createdLoadBalancerResponse.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
|
||||
public class LoadBalancerFactory : ILoadBalancerFactory
|
||||
{
|
||||
private readonly IServiceDiscoveryProviderFactory _serviceProviderFactory;
|
||||
private readonly IEnumerable<ILoadBalancerCreator> _loadBalancerCreators;
|
||||
|
||||
public LoadBalancerFactory(IServiceDiscoveryProviderFactory serviceProviderFactory, IEnumerable<ILoadBalancerCreator> loadBalancerCreators)
|
||||
{
|
||||
_serviceProviderFactory = serviceProviderFactory;
|
||||
_loadBalancerCreators = loadBalancerCreators;
|
||||
}
|
||||
|
||||
public Response<ILoadBalancer> Get(DownstreamRoute route, ServiceProviderConfiguration config)
|
||||
{
|
||||
var serviceProviderFactoryResponse = _serviceProviderFactory.Get(config, route);
|
||||
|
||||
if (serviceProviderFactoryResponse.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(serviceProviderFactoryResponse.Errors);
|
||||
}
|
||||
|
||||
var serviceProvider = serviceProviderFactoryResponse.Data;
|
||||
var requestedType = route.LoadBalancerOptions?.Type ?? nameof(NoLoadBalancer);
|
||||
var applicableCreator = _loadBalancerCreators.SingleOrDefault(c => c.Type == requestedType);
|
||||
|
||||
if (applicableCreator == null)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(new CouldNotFindLoadBalancerCreator($"Could not find load balancer creator for Type: {requestedType}, please check your config specified the correct load balancer and that you have registered a class with the same name."));
|
||||
}
|
||||
|
||||
var createdLoadBalancerResponse = applicableCreator.Create(route, serviceProvider);
|
||||
|
||||
if (createdLoadBalancerResponse.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(createdLoadBalancerResponse.Errors);
|
||||
}
|
||||
|
||||
return new OkResponse<ILoadBalancer>(createdLoadBalancerResponse.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,70 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
public class LoadBalancerHouse : ILoadBalancerHouse
|
||||
{
|
||||
private readonly ILoadBalancerFactory _factory;
|
||||
private readonly ConcurrentDictionary<string, ILoadBalancer> _loadBalancers;
|
||||
|
||||
public LoadBalancerHouse(ILoadBalancerFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
_loadBalancers = new ConcurrentDictionary<string, ILoadBalancer>();
|
||||
}
|
||||
|
||||
public Response<ILoadBalancer> Get(DownstreamReRoute reRoute, ServiceProviderConfiguration config)
|
||||
{
|
||||
try
|
||||
{
|
||||
Response<ILoadBalancer> result;
|
||||
|
||||
if (_loadBalancers.TryGetValue(reRoute.LoadBalancerKey, out var loadBalancer))
|
||||
{
|
||||
loadBalancer = _loadBalancers[reRoute.LoadBalancerKey];
|
||||
|
||||
if (reRoute.LoadBalancerOptions.Type != loadBalancer.GetType().Name)
|
||||
{
|
||||
result = _factory.Get(reRoute, config);
|
||||
if (result.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(result.Errors);
|
||||
}
|
||||
|
||||
loadBalancer = result.Data;
|
||||
AddLoadBalancer(reRoute.LoadBalancerKey, loadBalancer);
|
||||
}
|
||||
|
||||
return new OkResponse<ILoadBalancer>(loadBalancer);
|
||||
}
|
||||
|
||||
result = _factory.Get(reRoute, config);
|
||||
|
||||
if (result.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(result.Errors);
|
||||
}
|
||||
|
||||
loadBalancer = result.Data;
|
||||
AddLoadBalancer(reRoute.LoadBalancerKey, loadBalancer);
|
||||
return new OkResponse<ILoadBalancer>(loadBalancer);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
|
||||
{
|
||||
new UnableToFindLoadBalancerError($"unabe to find load balancer for {reRoute.LoadBalancerKey} exception is {ex}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoadBalancer(string key, ILoadBalancer loadBalancer)
|
||||
{
|
||||
_loadBalancers.AddOrUpdate(key, loadBalancer, (x, y) => loadBalancer);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
public class LoadBalancerHouse : ILoadBalancerHouse
|
||||
{
|
||||
private readonly ILoadBalancerFactory _factory;
|
||||
private readonly ConcurrentDictionary<string, ILoadBalancer> _loadBalancers;
|
||||
|
||||
public LoadBalancerHouse(ILoadBalancerFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
_loadBalancers = new ConcurrentDictionary<string, ILoadBalancer>();
|
||||
}
|
||||
|
||||
public Response<ILoadBalancer> Get(DownstreamRoute route, ServiceProviderConfiguration config)
|
||||
{
|
||||
try
|
||||
{
|
||||
Response<ILoadBalancer> result;
|
||||
|
||||
if (_loadBalancers.TryGetValue(route.LoadBalancerKey, out var loadBalancer))
|
||||
{
|
||||
loadBalancer = _loadBalancers[route.LoadBalancerKey];
|
||||
|
||||
if (route.LoadBalancerOptions.Type != loadBalancer.GetType().Name)
|
||||
{
|
||||
result = _factory.Get(route, config);
|
||||
if (result.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(result.Errors);
|
||||
}
|
||||
|
||||
loadBalancer = result.Data;
|
||||
AddLoadBalancer(route.LoadBalancerKey, loadBalancer);
|
||||
}
|
||||
|
||||
return new OkResponse<ILoadBalancer>(loadBalancer);
|
||||
}
|
||||
|
||||
result = _factory.Get(route, config);
|
||||
|
||||
if (result.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(result.Errors);
|
||||
}
|
||||
|
||||
loadBalancer = result.Data;
|
||||
AddLoadBalancer(route.LoadBalancerKey, loadBalancer);
|
||||
return new OkResponse<ILoadBalancer>(loadBalancer);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
|
||||
{
|
||||
new UnableToFindLoadBalancerError($"unabe to find load balancer for {route.LoadBalancerKey} exception is {ex}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoadBalancer(string key, ILoadBalancer loadBalancer)
|
||||
{
|
||||
_loadBalancers.AddOrUpdate(key, loadBalancer, (x, y) => loadBalancer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class NoLoadBalancerCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(new NoLoadBalancer(async () => await serviceProvider.Get()));
|
||||
}
|
||||
|
||||
public string Type => nameof(NoLoadBalancer);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class NoLoadBalancerCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(new NoLoadBalancer(async () => await serviceProvider.Get()));
|
||||
}
|
||||
|
||||
public string Type => nameof(NoLoadBalancer);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class RoundRobinCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(new RoundRobin(async () => await serviceProvider.Get()));
|
||||
}
|
||||
|
||||
public string Type => nameof(RoundRobin);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class RoundRobinCreator : ILoadBalancerCreator
|
||||
{
|
||||
public Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new OkResponse<ILoadBalancer>(new RoundRobin(async () => await serviceProvider.Get()));
|
||||
}
|
||||
|
||||
public string Type => nameof(RoundRobin);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace Ocelot.LoadBalancer.Middleware
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
@ -24,11 +24,11 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
var internalConfiguration = httpContext.Items.IInternalConfiguration();
|
||||
|
||||
var loadBalancer = _loadBalancerHouse.Get(downstreamReRoute, internalConfiguration.ServiceProviderConfiguration);
|
||||
var loadBalancer = _loadBalancerHouse.Get(downstreamRoute, internalConfiguration.ServiceProviderConfiguration);
|
||||
|
||||
if (loadBalancer.IsError)
|
||||
{
|
||||
@ -43,9 +43,9 @@
|
||||
Logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
|
||||
httpContext.Items.UpsertErrors(hostAndPort.Errors);
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
}
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
//todo check downstreamRequest is ok
|
||||
downstreamRequest.Host = hostAndPort.Data.DownstreamHost;
|
||||
|
@ -19,9 +19,9 @@
|
||||
input.Upsert("DownstreamResponse", downstreamResponse);
|
||||
}
|
||||
|
||||
public static void UpsertDownstreamReRoute(this IDictionary<object, object> input, DownstreamReRoute downstreamReRoute)
|
||||
public static void UpsertDownstreamRoute(this IDictionary<object, object> input, Configuration.DownstreamRoute downstreamRoute)
|
||||
{
|
||||
input.Upsert("DownstreamReRoute", downstreamReRoute);
|
||||
input.Upsert("DownstreamRoute", downstreamRoute);
|
||||
}
|
||||
|
||||
public static void UpsertTemplatePlaceholderNameAndValues(this IDictionary<object, object> input, List<PlaceholderNameAndValue> tPNV)
|
||||
@ -29,9 +29,9 @@
|
||||
input.Upsert("TemplatePlaceholderNameAndValues", tPNV);
|
||||
}
|
||||
|
||||
public static void UpsertDownstreamRoute(this IDictionary<object, object> input, DownstreamRoute downstreamRoute)
|
||||
public static void UpsertDownstreamRoute(this IDictionary<object, object> input, DownstreamRouteFinder.DownstreamRouteHolder downstreamRoute)
|
||||
{
|
||||
input.Upsert("DownstreamRoute", downstreamRoute);
|
||||
input.Upsert("DownstreamRouteHolder", downstreamRoute);
|
||||
}
|
||||
|
||||
public static void UpsertErrors(this IDictionary<object, object> input, List<Error> errors)
|
||||
@ -61,9 +61,9 @@
|
||||
return errors == null ? new List<Error>() : errors;
|
||||
}
|
||||
|
||||
public static DownstreamRoute DownstreamRoute(this IDictionary<object, object> input)
|
||||
public static DownstreamRouteFinder.DownstreamRouteHolder DownstreamRouteHolder(this IDictionary<object, object> input)
|
||||
{
|
||||
return input.Get<DownstreamRoute>("DownstreamRoute");
|
||||
return input.Get<DownstreamRouteFinder.DownstreamRouteHolder>("DownstreamRouteHolder");
|
||||
}
|
||||
|
||||
public static List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues(this IDictionary<object, object> input)
|
||||
@ -81,9 +81,9 @@
|
||||
return input.Get<DownstreamResponse>("DownstreamResponse");
|
||||
}
|
||||
|
||||
public static DownstreamReRoute DownstreamReRoute(this IDictionary<object, object> input)
|
||||
public static Configuration.DownstreamRoute DownstreamRoute(this IDictionary<object, object> input)
|
||||
{
|
||||
return input.Get<DownstreamReRoute>("DownstreamReRoute");
|
||||
return input.Get<Configuration.DownstreamRoute>("DownstreamRoute");
|
||||
}
|
||||
|
||||
private static T Get<T>(this IDictionary<object, object> input, string key)
|
||||
|
@ -5,6 +5,6 @@ namespace Ocelot.Multiplexer
|
||||
{
|
||||
public interface IDefinedAggregatorProvider
|
||||
{
|
||||
Response<IDefinedAggregator> Get(ReRoute reRoute);
|
||||
Response<IDefinedAggregator> Get(Route route);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@
|
||||
|
||||
public interface IResponseAggregator
|
||||
{
|
||||
Task Aggregate(ReRoute reRoute, HttpContext originalContext, List<HttpContext> downstreamResponses);
|
||||
Task Aggregate(Route route, HttpContext originalContext, List<HttpContext> downstreamResponses);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ namespace Ocelot.Multiplexer
|
||||
|
||||
public interface IResponseAggregatorFactory
|
||||
{
|
||||
IResponseAggregator Get(ReRoute reRoute);
|
||||
IResponseAggregator Get(Route route);
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ namespace Ocelot.Multiplexer
|
||||
_simple = responseAggregator;
|
||||
}
|
||||
|
||||
public IResponseAggregator Get(ReRoute reRoute)
|
||||
public IResponseAggregator Get(Route route)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(reRoute.Aggregator))
|
||||
if (!string.IsNullOrEmpty(route.Aggregator))
|
||||
{
|
||||
return _userDefined;
|
||||
}
|
||||
|
@ -29,19 +29,19 @@
|
||||
if (httpContext.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
//todo this is obviously stupid
|
||||
httpContext.Items.UpsertDownstreamReRoute(httpContext.Items.DownstreamRoute().ReRoute.DownstreamReRoute[0]);
|
||||
httpContext.Items.UpsertDownstreamRoute(httpContext.Items.DownstreamRouteHolder().Route.DownstreamRoute[0]);
|
||||
await _next.Invoke(httpContext);
|
||||
return;
|
||||
}
|
||||
|
||||
var reRouteKeysConfigs = httpContext.Items.DownstreamRoute().ReRoute.DownstreamReRouteConfig;
|
||||
if (reRouteKeysConfigs == null || !reRouteKeysConfigs.Any())
|
||||
var routeKeysConfigs = httpContext.Items.DownstreamRouteHolder().Route.DownstreamRouteConfig;
|
||||
if (routeKeysConfigs == null || !routeKeysConfigs.Any())
|
||||
{
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
var downstreamRouteHolder = httpContext.Items.DownstreamRouteHolder();
|
||||
|
||||
var tasks = new Task<HttpContext>[downstreamRoute.ReRoute.DownstreamReRoute.Count];
|
||||
var tasks = new Task<HttpContext>[downstreamRouteHolder.Route.DownstreamRoute.Count];
|
||||
|
||||
for (var i = 0; i < downstreamRoute.ReRoute.DownstreamReRoute.Count; i++)
|
||||
for (var i = 0; i < downstreamRouteHolder.Route.DownstreamRoute.Count; i++)
|
||||
{
|
||||
var newHttpContext = Copy(httpContext);
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
newHttpContext.Items
|
||||
.UpsertTemplatePlaceholderNameAndValues(httpContext.Items.TemplatePlaceholderNameAndValues());
|
||||
newHttpContext.Items
|
||||
.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[i]);
|
||||
.UpsertDownstreamRoute(downstreamRouteHolder.Route.DownstreamRoute[i]);
|
||||
|
||||
tasks[i] = Fire(newHttpContext, _next);
|
||||
}
|
||||
@ -67,14 +67,14 @@
|
||||
contexts.Add(finished);
|
||||
}
|
||||
|
||||
await Map(httpContext, downstreamRoute.ReRoute, contexts);
|
||||
await Map(httpContext, downstreamRouteHolder.Route, contexts);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpContext.Items.UpsertDownstreamReRoute(httpContext.Items.DownstreamRoute().ReRoute.DownstreamReRoute[0]);
|
||||
httpContext.Items.UpsertDownstreamRoute(httpContext.Items.DownstreamRouteHolder().Route.DownstreamRoute[0]);
|
||||
var mainResponse = await Fire(httpContext, _next);
|
||||
|
||||
if (httpContext.Items.DownstreamRoute().ReRoute.DownstreamReRoute.Count == 1)
|
||||
if (httpContext.Items.DownstreamRouteHolder().Route.DownstreamRoute.Count == 1)
|
||||
{
|
||||
MapNotAggregate(httpContext, new List<HttpContext>() { mainResponse });
|
||||
return;
|
||||
@ -91,14 +91,14 @@
|
||||
|
||||
var jObject = Newtonsoft.Json.Linq.JToken.Parse(content);
|
||||
|
||||
for (var i = 1; i < httpContext.Items.DownstreamRoute().ReRoute.DownstreamReRoute.Count; i++)
|
||||
for (var i = 1; i < httpContext.Items.DownstreamRouteHolder().Route.DownstreamRoute.Count; i++)
|
||||
{
|
||||
var templatePlaceholderNameAndValues = httpContext.Items.TemplatePlaceholderNameAndValues();
|
||||
|
||||
var downstreamReRoute = httpContext.Items.DownstreamRoute().ReRoute.DownstreamReRoute[i];
|
||||
var downstreamRoute = httpContext.Items.DownstreamRouteHolder().Route.DownstreamRoute[i];
|
||||
|
||||
var matchAdvancedAgg = reRouteKeysConfigs
|
||||
.FirstOrDefault(q => q.ReRouteKey == downstreamReRoute.Key);
|
||||
var matchAdvancedAgg = routeKeysConfigs
|
||||
.FirstOrDefault(q => q.RouteKey == downstreamRoute.Key);
|
||||
|
||||
if (matchAdvancedAgg != null)
|
||||
{
|
||||
@ -121,7 +121,7 @@
|
||||
.UpsertTemplatePlaceholderNameAndValues(tPNV);
|
||||
|
||||
newHttpContext.Items
|
||||
.UpsertDownstreamReRoute(downstreamReRoute);
|
||||
.UpsertDownstreamRoute(downstreamRoute);
|
||||
|
||||
tasks.Add(Fire(newHttpContext, _next));
|
||||
}
|
||||
@ -140,7 +140,7 @@
|
||||
.UpsertTemplatePlaceholderNameAndValues(templatePlaceholderNameAndValues);
|
||||
|
||||
newHttpContext.Items
|
||||
.UpsertDownstreamReRoute(downstreamReRoute);
|
||||
.UpsertDownstreamRoute(downstreamRoute);
|
||||
|
||||
tasks.Add(Fire(newHttpContext, _next));
|
||||
}
|
||||
@ -156,7 +156,7 @@
|
||||
contexts.Add(finished);
|
||||
}
|
||||
|
||||
await Map(httpContext, httpContext.Items.DownstreamRoute().ReRoute, contexts);
|
||||
await Map(httpContext, httpContext.Items.DownstreamRouteHolder().Route, contexts);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,12 +187,12 @@
|
||||
return target;
|
||||
}
|
||||
|
||||
private async Task Map(HttpContext httpContext, ReRoute reRoute, List<HttpContext> contexts)
|
||||
private async Task Map(HttpContext httpContext, Route route, List<HttpContext> contexts)
|
||||
{
|
||||
if (reRoute.DownstreamReRoute.Count > 1)
|
||||
if (route.DownstreamRoute.Count > 1)
|
||||
{
|
||||
var aggregator = _factory.Get(reRoute);
|
||||
await aggregator.Aggregate(reRoute, httpContext, contexts);
|
||||
var aggregator = _factory.Get(route);
|
||||
await aggregator.Aggregate(route, httpContext, contexts);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -16,14 +16,14 @@ namespace Ocelot.Multiplexer
|
||||
_aggregators = services.GetServices<IDefinedAggregator>().ToDictionary(x => x.GetType().Name);
|
||||
}
|
||||
|
||||
public Response<IDefinedAggregator> Get(ReRoute reRoute)
|
||||
public Response<IDefinedAggregator> Get(Route route)
|
||||
{
|
||||
if (_aggregators.ContainsKey(reRoute.Aggregator))
|
||||
if (_aggregators.ContainsKey(route.Aggregator))
|
||||
{
|
||||
return new OkResponse<IDefinedAggregator>(_aggregators[reRoute.Aggregator]);
|
||||
return new OkResponse<IDefinedAggregator>(_aggregators[route.Aggregator]);
|
||||
}
|
||||
|
||||
return new ErrorResponse<IDefinedAggregator>(new CouldNotFindAggregatorError(reRoute.Aggregator));
|
||||
return new ErrorResponse<IDefinedAggregator>(new CouldNotFindAggregatorError(route.Aggregator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace Ocelot.Multiplexer
|
||||
{
|
||||
public class SimpleJsonResponseAggregator : IResponseAggregator
|
||||
{
|
||||
public async Task Aggregate(ReRoute reRoute, HttpContext originalContext, List<HttpContext> downstreamContexts)
|
||||
public async Task Aggregate(Route route, HttpContext originalContext, List<HttpContext> downstreamContexts)
|
||||
{
|
||||
await MapAggregateContent(originalContext, downstreamContexts);
|
||||
}
|
||||
@ -24,11 +24,11 @@ namespace Ocelot.Multiplexer
|
||||
|
||||
contentBuilder.Append("{");
|
||||
|
||||
var responseKeys = downstreamContexts.Select(s => s.Items.DownstreamReRoute().Key).Distinct().ToList();
|
||||
var responseKeys = downstreamContexts.Select(s => s.Items.DownstreamRoute().Key).Distinct().ToList();
|
||||
|
||||
for (var k = 0; k < responseKeys.Count; k++)
|
||||
{
|
||||
var contexts = downstreamContexts.Where(w => w.Items.DownstreamReRoute().Key == responseKeys[k]).ToList();
|
||||
var contexts = downstreamContexts.Where(w => w.Items.DownstreamRoute().Key == responseKeys[k]).ToList();
|
||||
if (contexts.Count == 1)
|
||||
{
|
||||
if (contexts[0].Items.Errors().Count > 0)
|
||||
|
@ -15,9 +15,9 @@ namespace Ocelot.Multiplexer
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
public async Task Aggregate(ReRoute reRoute, HttpContext originalContext, List<HttpContext> downstreamResponses)
|
||||
public async Task Aggregate(Route route, HttpContext originalContext, List<HttpContext> downstreamResponses)
|
||||
{
|
||||
var aggregator = _provider.Get(reRoute);
|
||||
var aggregator = _provider.Get(route);
|
||||
|
||||
if (!aggregator.IsError)
|
||||
{
|
||||
|
@ -4,9 +4,9 @@
|
||||
using Ocelot.Middleware;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class ClaimsToQueryStringMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
@ -23,15 +23,15 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
if (downstreamReRoute.ClaimsToQueries.Any())
|
||||
if (downstreamRoute.ClaimsToQueries.Any())
|
||||
{
|
||||
Logger.LogInformation($"{downstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
|
||||
|
||||
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
||||
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(downstreamReRoute.ClaimsToQueries, httpContext.User.Claims, downstreamRequest);
|
||||
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(downstreamRoute.ClaimsToQueries, httpContext.User.Claims, downstreamRequest);
|
||||
|
||||
if (response.IsError)
|
||||
{
|
||||
|
@ -26,14 +26,14 @@
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
var options = downstreamReRoute.RateLimitOptions;
|
||||
var options = downstreamRoute.RateLimitOptions;
|
||||
|
||||
// check if rate limiting is enabled
|
||||
if (!downstreamReRoute.EnableEndpointEndpointRateLimiting)
|
||||
if (!downstreamRoute.EnableEndpointEndpointRateLimiting)
|
||||
{
|
||||
Logger.LogInformation($"EndpointRateLimiting is not enabled for {downstreamReRoute.DownstreamPathTemplate.Value}");
|
||||
Logger.LogInformation($"EndpointRateLimiting is not enabled for {downstreamRoute.DownstreamPathTemplate.Value}");
|
||||
await _next.Invoke(httpContext);
|
||||
return;
|
||||
}
|
||||
@ -44,7 +44,7 @@
|
||||
// check white list
|
||||
if (IsWhitelisted(identity, options))
|
||||
{
|
||||
Logger.LogInformation($"{downstreamReRoute.DownstreamPathTemplate.Value} is white listed from rate limiting");
|
||||
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} is white listed from rate limiting");
|
||||
await _next.Invoke(httpContext);
|
||||
return;
|
||||
}
|
||||
@ -62,7 +62,7 @@
|
||||
var retryAfter = _processor.RetryAfterFrom(counter.Timestamp, rule);
|
||||
|
||||
// log blocked request
|
||||
LogBlockedRequest(httpContext, identity, counter, rule, downstreamReRoute);
|
||||
LogBlockedRequest(httpContext, identity, counter, rule, downstreamRoute);
|
||||
|
||||
var retrystring = retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
|
||||
@ -112,10 +112,10 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule, DownstreamReRoute downstreamReRoute)
|
||||
public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule, DownstreamRoute downstreamRoute)
|
||||
{
|
||||
Logger.LogInformation(
|
||||
$"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule { downstreamReRoute.UpstreamPathTemplate.OriginalValue }, TraceIdentifier {httpContext.TraceIdentifier}.");
|
||||
$"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule { downstreamRoute.UpstreamPathTemplate.OriginalValue }, TraceIdentifier {httpContext.TraceIdentifier}.");
|
||||
}
|
||||
|
||||
public virtual DownstreamResponse ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitOptions option, string retryAfter)
|
||||
|
@ -1,13 +1,13 @@
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface IRequestMapper
|
||||
{
|
||||
Task<Response<HttpRequestMessage>> Map(HttpRequest request, DownstreamReRoute downstreamReRoute);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface IRequestMapper
|
||||
{
|
||||
Task<Response<HttpRequestMessage>> Map(HttpRequest request, DownstreamRoute downstreamRoute);
|
||||
}
|
||||
}
|
||||
|
@ -1,119 +1,119 @@
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class RequestMapper : IRequestMapper
|
||||
{
|
||||
private readonly string[] _unsupportedHeaders = { "host" };
|
||||
|
||||
public async Task<Response<HttpRequestMessage>> Map(HttpRequest request, DownstreamReRoute downstreamReRoute)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage()
|
||||
{
|
||||
Content = await MapContent(request),
|
||||
Method = MapMethod(request, downstreamReRoute),
|
||||
RequestUri = MapUri(request),
|
||||
Version = downstreamReRoute.DownstreamHttpVersion,
|
||||
};
|
||||
|
||||
MapHeaders(request, requestMessage);
|
||||
|
||||
return new OkResponse<HttpRequestMessage>(requestMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(ex));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<HttpContent> MapContent(HttpRequest request)
|
||||
{
|
||||
if (request.Body == null || (request.Body.CanSeek && request.Body.Length <= 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Never change this to StreamContent again, I forgot it doesnt work in #464.
|
||||
var content = new ByteArrayContent(await ToByteArray(request.Body));
|
||||
|
||||
if (!string.IsNullOrEmpty(request.ContentType))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation("Content-Type", new[] { request.ContentType });
|
||||
}
|
||||
|
||||
AddHeaderIfExistsOnRequest("Content-Language", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Location", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Range", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-MD5", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Disposition", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Encoding", content, request);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private void AddHeaderIfExistsOnRequest(string key, HttpContent content, HttpRequest request)
|
||||
{
|
||||
if (request.Headers.ContainsKey(key))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation(key, request.Headers[key].ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private HttpMethod MapMethod(HttpRequest request, DownstreamReRoute downstreamReRoute)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(downstreamReRoute?.DownstreamHttpMethod))
|
||||
{
|
||||
return new HttpMethod(downstreamReRoute.DownstreamHttpMethod);
|
||||
}
|
||||
|
||||
return new HttpMethod(request.Method);
|
||||
}
|
||||
|
||||
private Uri MapUri(HttpRequest request)
|
||||
{
|
||||
return new Uri(request.GetEncodedUrl());
|
||||
}
|
||||
|
||||
private void MapHeaders(HttpRequest request, HttpRequestMessage requestMessage)
|
||||
{
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
if (IsSupportedHeader(header))
|
||||
{
|
||||
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSupportedHeader(KeyValuePair<string, StringValues> header)
|
||||
{
|
||||
return !_unsupportedHeaders.Contains(header.Key.ToLower());
|
||||
}
|
||||
|
||||
private async Task<byte[]> ToByteArray(Stream stream)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
using (var memStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memStream);
|
||||
return memStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class RequestMapper : IRequestMapper
|
||||
{
|
||||
private readonly string[] _unsupportedHeaders = { "host" };
|
||||
|
||||
public async Task<Response<HttpRequestMessage>> Map(HttpRequest request, DownstreamRoute downstreamRoute)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage()
|
||||
{
|
||||
Content = await MapContent(request),
|
||||
Method = MapMethod(request, downstreamRoute),
|
||||
RequestUri = MapUri(request),
|
||||
Version = downstreamRoute.DownstreamHttpVersion,
|
||||
};
|
||||
|
||||
MapHeaders(request, requestMessage);
|
||||
|
||||
return new OkResponse<HttpRequestMessage>(requestMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(ex));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<HttpContent> MapContent(HttpRequest request)
|
||||
{
|
||||
if (request.Body == null || (request.Body.CanSeek && request.Body.Length <= 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Never change this to StreamContent again, I forgot it doesnt work in #464.
|
||||
var content = new ByteArrayContent(await ToByteArray(request.Body));
|
||||
|
||||
if (!string.IsNullOrEmpty(request.ContentType))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation("Content-Type", new[] { request.ContentType });
|
||||
}
|
||||
|
||||
AddHeaderIfExistsOnRequest("Content-Language", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Location", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Range", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-MD5", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Disposition", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Encoding", content, request);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private void AddHeaderIfExistsOnRequest(string key, HttpContent content, HttpRequest request)
|
||||
{
|
||||
if (request.Headers.ContainsKey(key))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation(key, request.Headers[key].ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private HttpMethod MapMethod(HttpRequest request, DownstreamRoute downstreamRoute)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(downstreamRoute?.DownstreamHttpMethod))
|
||||
{
|
||||
return new HttpMethod(downstreamRoute.DownstreamHttpMethod);
|
||||
}
|
||||
|
||||
return new HttpMethod(request.Method);
|
||||
}
|
||||
|
||||
private Uri MapUri(HttpRequest request)
|
||||
{
|
||||
return new Uri(request.GetEncodedUrl());
|
||||
}
|
||||
|
||||
private void MapHeaders(HttpRequest request, HttpRequestMessage requestMessage)
|
||||
{
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
if (IsSupportedHeader(header))
|
||||
{
|
||||
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSupportedHeader(KeyValuePair<string, StringValues> header)
|
||||
{
|
||||
return !_unsupportedHeaders.Contains(header.Key.ToLower());
|
||||
}
|
||||
|
||||
private async Task<byte[]> ToByteArray(Stream stream)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
using (var memStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memStream);
|
||||
return memStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ namespace Ocelot.Request.Middleware
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
var httpRequestMessage = await _requestMapper.Map(httpContext.Request, downstreamReRoute);
|
||||
var httpRequestMessage = await _requestMapper.Map(httpContext.Request, downstreamRoute);
|
||||
|
||||
if (httpRequestMessage.IsError)
|
||||
{
|
||||
|
@ -11,14 +11,14 @@ namespace Ocelot.RequestId.Middleware
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class ReRouteRequestIdMiddleware : OcelotMiddleware
|
||||
public class RequestIdMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
|
||||
public ReRouteRequestIdMiddleware(RequestDelegate next,
|
||||
public RequestIdMiddleware(RequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
IRequestScopedDataRepository requestScopedDataRepository)
|
||||
: base(loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>())
|
||||
: base(loggerFactory.CreateLogger<RequestIdMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
_requestScopedDataRepository = requestScopedDataRepository;
|
||||
@ -32,9 +32,9 @@ namespace Ocelot.RequestId.Middleware
|
||||
|
||||
private void SetOcelotRequestId(HttpContext httpContext)
|
||||
{
|
||||
var downstreamReRoute = httpContext.Items.DownstreamReRoute();
|
||||
var downstreamRoute = httpContext.Items.DownstreamRoute();
|
||||
|
||||
var key = downstreamReRoute.RequestIdKey ?? DefaultRequestIdKey.Value;
|
||||
var key = downstreamRoute.RequestIdKey ?? DefaultRequestIdKey.Value;
|
||||
|
||||
if (httpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
|
||||
{
|
||||
@ -52,7 +52,7 @@ namespace Ocelot.RequestId.Middleware
|
||||
}
|
||||
}
|
||||
|
||||
var requestId = new RequestId(downstreamReRoute.RequestIdKey, httpContext.TraceIdentifier);
|
||||
var requestId = new RequestId(downstreamRoute.RequestIdKey, httpContext.TraceIdentifier);
|
||||
|
||||
var downstreamRequest = httpContext.Items.DownstreamRequest();
|
||||
|
@ -6,7 +6,7 @@ namespace Ocelot.RequestId.Middleware
|
||||
{
|
||||
public static IApplicationBuilder UseRequestIdMiddleware(this IApplicationBuilder builder)
|
||||
{
|
||||
return builder.UseMiddleware<ReRouteRequestIdMiddleware>();
|
||||
return builder.UseMiddleware<RequestIdMiddleware>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user