Rename all ReRoute to Route to move closer to YARP +semver: breaking

This commit is contained in:
Tom Pallister
2020-05-23 20:50:05 +01:00
committed by GitHub
parent fe3e8bd23a
commit 3439be8927
269 changed files with 23591 additions and 23605 deletions

View File

@ -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;
};
}
}

View File

@ -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;
};
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -4,6 +4,6 @@ namespace Ocelot.Cache
{
public interface IRegionCreator
{
string Create(FileReRoute reRoute);
string Create(FileRoute route);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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)
{

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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
);
}
}
}

View 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
);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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
);
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
{
public interface IAuthenticationOptionsCreator
{
AuthenticationOptions Create(FileReRoute reRoute);
AuthenticationOptions Create(FileRoute route);
}
}
}

View File

@ -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);
}
}

View File

@ -5,6 +5,6 @@ namespace Ocelot.Configuration.Creator
{
public interface IDownstreamAddressesCreator
{
List<DownstreamHostAndPort> Create(FileReRoute reRoute);
List<DownstreamHostAndPort> Create(FileRoute route);
}
}
}

View File

@ -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);
}
}

View File

@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
{
public interface IHeaderFindAndReplaceCreator
{
HeaderTransformations Create(FileReRoute fileReRoute);
HeaderTransformations Create(FileRoute fileRoute);
}
}
}

View File

@ -7,6 +7,6 @@ namespace Ocelot.Configuration.Creator
/// </summary>
public interface IHttpHandlerOptionsCreator
{
HttpHandlerOptions Create(FileHttpHandlerOptions fileReRoute);
HttpHandlerOptions Create(FileHttpHandlerOptions fileRoute);
}
}
}

View File

@ -1,9 +0,0 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IReRouteKeyCreator
{
string Create(FileReRoute fileReRoute);
}
}

View File

@ -1,9 +0,0 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IReRouteOptionsCreator
{
ReRouteOptions Create(FileReRoute fileReRoute);
}
}

View File

@ -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);
}
}

View File

@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
{
public interface IRequestIdKeyCreator
{
string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration);
string Create(FileRoute fileRoute, FileGlobalConfiguration globalConfiguration);
}
}

View File

@ -0,0 +1,9 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IRouteKeyCreator
{
string Create(FileRoute fileRoute);
}
}

View File

@ -0,0 +1,9 @@
using Ocelot.Configuration.File;
namespace Ocelot.Configuration.Creator
{
public interface IRouteOptionsCreator
{
RouteOptions Create(FileRoute fileRoute);
}
}

View File

@ -5,6 +5,6 @@ namespace Ocelot.Configuration.Creator
{
public interface IUpstreamTemplatePatternCreator
{
UpstreamPathTemplate Create(IReRoute reRoute);
UpstreamPathTemplate Create(IRoute route);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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] == '{';
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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!");
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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)
{
}
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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)
{

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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; }
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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)

View File

@ -5,6 +5,6 @@ namespace Ocelot.Multiplexer
{
public interface IDefinedAggregatorProvider
{
Response<IDefinedAggregator> Get(ReRoute reRoute);
Response<IDefinedAggregator> Get(Route route);
}
}

View File

@ -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);
}
}

View File

@ -4,6 +4,6 @@ namespace Ocelot.Multiplexer
public interface IResponseAggregatorFactory
{
IResponseAggregator Get(ReRoute reRoute);
IResponseAggregator Get(Route route);
}
}

View File

@ -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;
}

View File

@ -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
{

View File

@ -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));
}
}
}

View File

@ -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)

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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)
{

View File

@ -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();

View File

@ -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