mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 12:10:50 +08:00 
			
		
		
		
	added a new implementation that stores the ocelot config in consul kv store, had to change some major things and add cache settings as default
This commit is contained in:
		@@ -5,6 +5,7 @@ namespace Ocelot.Cache
 | 
				
			|||||||
    public interface IOcelotCache<T>
 | 
					    public interface IOcelotCache<T>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        void Add(string key, T value, TimeSpan ttl);
 | 
					        void Add(string key, T value, TimeSpan ttl);
 | 
				
			||||||
 | 
					        void AddAndDelete(string key, T value, TimeSpan ttl);
 | 
				
			||||||
        T Get(string key);
 | 
					        T Get(string key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,18 @@ namespace Ocelot.Cache
 | 
				
			|||||||
            _cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
 | 
					            _cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void AddAndDelete(string key, T value, TimeSpan ttl)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var exists = _cacheManager.Get(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (exists != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _cacheManager.Remove(key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public T Get(string key)
 | 
					        public T Get(string key)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return _cacheManager.Get<T>(key);
 | 
					            return _cacheManager.Get<T>(key);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ namespace Ocelot.Configuration.Creator
 | 
				
			|||||||
                    .WithQuotaExceededMessage(globalConfiguration.RateLimitOptions.QuotaExceededMessage)
 | 
					                    .WithQuotaExceededMessage(globalConfiguration.RateLimitOptions.QuotaExceededMessage)
 | 
				
			||||||
                    .WithRateLimitCounterPrefix(globalConfiguration.RateLimitOptions.RateLimitCounterPrefix)
 | 
					                    .WithRateLimitCounterPrefix(globalConfiguration.RateLimitOptions.RateLimitCounterPrefix)
 | 
				
			||||||
                    .WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
 | 
					                    .WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
 | 
				
			||||||
                        TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan),
 | 
					                        fileReRoute.RateLimitOptions.PeriodTimespan,
 | 
				
			||||||
                        fileReRoute.RateLimitOptions.Limit))
 | 
					                        fileReRoute.RateLimitOptions.Limit))
 | 
				
			||||||
                    .Build();
 | 
					                    .Build();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
using Ocelot.Responses;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Configuration.Provider
 | 
					namespace Ocelot.Configuration.Provider
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public interface IOcelotConfigurationProvider
 | 
					    public interface IOcelotConfigurationProvider
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Response<IOcelotConfiguration> Get();
 | 
					        Task<Response<IOcelotConfiguration>> Get();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
using Ocelot.Configuration.Repository;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Ocelot.Configuration.Repository;
 | 
				
			||||||
using Ocelot.Responses;
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Configuration.Provider
 | 
					namespace Ocelot.Configuration.Provider
 | 
				
			||||||
@@ -15,9 +16,9 @@ namespace Ocelot.Configuration.Provider
 | 
				
			|||||||
            _repo = repo;
 | 
					            _repo = repo;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Response<IOcelotConfiguration> Get()
 | 
					        public async Task<Response<IOcelotConfiguration>> Get()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var repoConfig = _repo.Get();
 | 
					            var repoConfig = await _repo.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (repoConfig.IsError)
 | 
					            if (repoConfig.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
using System;
 | 
					using Polly.Timeout;
 | 
				
			||||||
using Polly.Timeout;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Configuration
 | 
					namespace Ocelot.Configuration
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -12,17 +11,17 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
            TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
 | 
					            TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
 | 
					            ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
 | 
				
			||||||
            DurationOfBreak = TimeSpan.FromMilliseconds(durationofBreak);
 | 
					            DurationOfBreak = durationofBreak;
 | 
				
			||||||
            TimeoutValue = TimeSpan.FromMilliseconds(timeoutValue);
 | 
					            TimeoutValue = timeoutValue;
 | 
				
			||||||
            TimeoutStrategy = timeoutStrategy;
 | 
					            TimeoutStrategy = timeoutStrategy;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
         
 | 
					         
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public int ExceptionsAllowedBeforeBreaking { get; private set; }
 | 
					        public int ExceptionsAllowedBeforeBreaking { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public TimeSpan DurationOfBreak { get; private set; }
 | 
					        public int DurationOfBreak { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public TimeSpan TimeoutValue { get; private set; }
 | 
					        public int TimeoutValue { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public TimeoutStrategy TimeoutStrategy { get; private set; }
 | 
					        public TimeoutStrategy TimeoutStrategy { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
using System;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,25 +58,4 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public bool DisableRateLimitHeaders { get; private set; }
 | 
					        public bool DisableRateLimitHeaders { get; private set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public class RateLimitRule
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public RateLimitRule(string period, TimeSpan periodTimespan, long limit)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            Period = period;
 | 
					 | 
				
			||||||
            PeriodTimespan = periodTimespan;
 | 
					 | 
				
			||||||
            Limit = limit;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Rate limit period as in 1s, 1m, 1h,1d
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        public string Period { get; private set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public TimeSpan PeriodTimespan { get; private set; }
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Maximum number of requests that a client can make in a defined period
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        public long Limit { get; private set; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								src/Ocelot/Configuration/RateLimitRule.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/Ocelot/Configuration/RateLimitRule.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.Configuration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class RateLimitRule
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public RateLimitRule(string period, double periodTimespan, long limit)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Period = period;
 | 
				
			||||||
 | 
					            PeriodTimespan = periodTimespan;
 | 
				
			||||||
 | 
					            Limit = limit;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Rate limit period as in 1s, 1m, 1h,1d
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public string Period { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public double PeriodTimespan { get; private set; }
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Maximum number of requests that a client can make in a defined period
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public long Limit { get; private set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,12 +7,12 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
    public class ReRoute
 | 
					    public class ReRoute
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public ReRoute(PathTemplate downstreamPathTemplate, 
 | 
					        public ReRoute(PathTemplate downstreamPathTemplate, 
 | 
				
			||||||
            PathTemplate upstreamTemplate, 
 | 
					            PathTemplate upstreamPathTemplate, 
 | 
				
			||||||
            HttpMethod upstreamHttpMethod, 
 | 
					            HttpMethod upstreamHttpMethod, 
 | 
				
			||||||
            string upstreamTemplatePattern, 
 | 
					            string upstreamTemplatePattern, 
 | 
				
			||||||
            bool isAuthenticated, 
 | 
					            bool isAuthenticated, 
 | 
				
			||||||
            AuthenticationOptions authenticationOptions, 
 | 
					            AuthenticationOptions authenticationOptions, 
 | 
				
			||||||
            List<ClaimToThing> configurationHeaderExtractorProperties, 
 | 
					            List<ClaimToThing> claimsToHeaders, 
 | 
				
			||||||
            List<ClaimToThing> claimsToClaims, 
 | 
					            List<ClaimToThing> claimsToClaims, 
 | 
				
			||||||
            Dictionary<string, string> routeClaimsRequirement, 
 | 
					            Dictionary<string, string> routeClaimsRequirement, 
 | 
				
			||||||
            bool isAuthorised, 
 | 
					            bool isAuthorised, 
 | 
				
			||||||
@@ -27,8 +27,8 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
            string reRouteKey, 
 | 
					            string reRouteKey, 
 | 
				
			||||||
            ServiceProviderConfiguration serviceProviderConfiguraion,
 | 
					            ServiceProviderConfiguration serviceProviderConfiguraion,
 | 
				
			||||||
            bool isQos,
 | 
					            bool isQos,
 | 
				
			||||||
            QoSOptions qos,
 | 
					            QoSOptions qosOptions,
 | 
				
			||||||
            bool enableRateLimit,
 | 
					            bool enableEndpointRateLimiting,
 | 
				
			||||||
            RateLimitOptions ratelimitOptions)
 | 
					            RateLimitOptions ratelimitOptions)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ReRouteKey = reRouteKey;
 | 
					            ReRouteKey = reRouteKey;
 | 
				
			||||||
@@ -37,7 +37,7 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
            DownstreamHost = downstreamHost;
 | 
					            DownstreamHost = downstreamHost;
 | 
				
			||||||
            DownstreamPort = downstreamPort;
 | 
					            DownstreamPort = downstreamPort;
 | 
				
			||||||
            DownstreamPathTemplate = downstreamPathTemplate;
 | 
					            DownstreamPathTemplate = downstreamPathTemplate;
 | 
				
			||||||
            UpstreamPathTemplate = upstreamTemplate;
 | 
					            UpstreamPathTemplate = upstreamPathTemplate;
 | 
				
			||||||
            UpstreamHttpMethod = upstreamHttpMethod;
 | 
					            UpstreamHttpMethod = upstreamHttpMethod;
 | 
				
			||||||
            UpstreamTemplatePattern = upstreamTemplatePattern;
 | 
					            UpstreamTemplatePattern = upstreamTemplatePattern;
 | 
				
			||||||
            IsAuthenticated = isAuthenticated;
 | 
					            IsAuthenticated = isAuthenticated;
 | 
				
			||||||
@@ -51,12 +51,12 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
                ?? new List<ClaimToThing>();
 | 
					                ?? new List<ClaimToThing>();
 | 
				
			||||||
            ClaimsToClaims = claimsToClaims 
 | 
					            ClaimsToClaims = claimsToClaims 
 | 
				
			||||||
                ?? new List<ClaimToThing>();
 | 
					                ?? new List<ClaimToThing>();
 | 
				
			||||||
            ClaimsToHeaders = configurationHeaderExtractorProperties 
 | 
					            ClaimsToHeaders = claimsToHeaders 
 | 
				
			||||||
                ?? new List<ClaimToThing>();
 | 
					                ?? new List<ClaimToThing>();
 | 
				
			||||||
            DownstreamScheme = downstreamScheme;
 | 
					            DownstreamScheme = downstreamScheme;
 | 
				
			||||||
            IsQos = isQos;
 | 
					            IsQos = isQos;
 | 
				
			||||||
            QosOptions = qos;
 | 
					            QosOptionsOptions = qosOptions;
 | 
				
			||||||
            EnableEndpointRateLimiting = enableRateLimit;
 | 
					            EnableEndpointEndpointRateLimiting = enableEndpointRateLimiting;
 | 
				
			||||||
            RateLimitOptions = ratelimitOptions;
 | 
					            RateLimitOptions = ratelimitOptions;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -77,12 +77,12 @@ namespace Ocelot.Configuration
 | 
				
			|||||||
        public CacheOptions FileCacheOptions { get; private set; }
 | 
					        public CacheOptions FileCacheOptions { get; private set; }
 | 
				
			||||||
        public string DownstreamScheme {get;private set;}
 | 
					        public string DownstreamScheme {get;private set;}
 | 
				
			||||||
        public bool IsQos { get; private set; }
 | 
					        public bool IsQos { get; private set; }
 | 
				
			||||||
        public QoSOptions QosOptions { get; private set; }
 | 
					        public QoSOptions QosOptionsOptions { get; private set; }
 | 
				
			||||||
        public string LoadBalancer {get;private set;}
 | 
					        public string LoadBalancer {get;private set;}
 | 
				
			||||||
        public string DownstreamHost { get; private set; }
 | 
					        public string DownstreamHost { get; private set; }
 | 
				
			||||||
        public int DownstreamPort { get; private set; }
 | 
					        public int DownstreamPort { get; private set; }
 | 
				
			||||||
        public ServiceProviderConfiguration ServiceProviderConfiguraion { get; private set; }
 | 
					        public ServiceProviderConfiguration ServiceProviderConfiguraion { get; private set; }
 | 
				
			||||||
        public bool EnableEndpointRateLimiting { get; private set; }
 | 
					        public bool EnableEndpointEndpointRateLimiting { get; private set; }
 | 
				
			||||||
        public RateLimitOptions RateLimitOptions { get; private set; }
 | 
					        public RateLimitOptions RateLimitOptions { get; private set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Consul;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using Newtonsoft.Json.Linq;
 | 
				
			||||||
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					using Ocelot.ServiceDiscovery;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.Configuration.Repository
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class ConsulOcelotConfigurationRepository : IOcelotConfigurationRepository
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly ConsulClient _consul;
 | 
				
			||||||
 | 
					        private ConsulRegistryConfiguration _configuration;
 | 
				
			||||||
 | 
					        private string _ocelotConfiguration = "OcelotConfiguration";
 | 
				
			||||||
 | 
					        private Cache.IOcelotCache<IOcelotConfiguration> _cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ConsulOcelotConfigurationRepository(ConsulRegistryConfiguration consulRegistryConfiguration, Cache.IOcelotCache<IOcelotConfiguration> cache)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName;
 | 
				
			||||||
 | 
					            var consulPort = consulRegistryConfiguration?.Port ?? 8500;
 | 
				
			||||||
 | 
					            _configuration = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.ServiceName);
 | 
				
			||||||
 | 
					            _cache = cache;
 | 
				
			||||||
 | 
					            _consul = new ConsulClient(config =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                config.Address = new Uri($"http://{_configuration.HostName}:{_configuration.Port}");
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<Response<IOcelotConfiguration>> Get()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var config = _cache.Get(_ocelotConfiguration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (config != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new OkResponse<IOcelotConfiguration>(config);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var queryResult = await _consul.KV.Get(_ocelotConfiguration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (queryResult.Response == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new OkResponse<IOcelotConfiguration>(null);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var bytes = queryResult.Response.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var json = Encoding.UTF8.GetString(bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var consulConfig = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new OkResponse<IOcelotConfiguration>(consulConfig);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var json = JsonConvert.SerializeObject(ocelotConfiguration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var bytes = Encoding.UTF8.GetBytes(json);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var kvPair = new KVPair(_ocelotConfiguration)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Value = bytes
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var result = await _consul.KV.Put(kvPair);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (result.Response)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return new OkResponse();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new ErrorResponse(new UnableToSetConfigInConsulError("Unable to set config in consul"));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
using Ocelot.Responses;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Configuration.Repository
 | 
					namespace Ocelot.Configuration.Repository
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public interface IOcelotConfigurationRepository
 | 
					    public interface IOcelotConfigurationRepository
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Response<IOcelotConfiguration> Get();
 | 
					        Task<Response<IOcelotConfiguration>> Get();
 | 
				
			||||||
        Response AddOrReplace(IOcelotConfiguration ocelotConfiguration);
 | 
					        Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
using Ocelot.Responses;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Configuration.Repository
 | 
					namespace Ocelot.Configuration.Repository
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -11,12 +12,12 @@ namespace Ocelot.Configuration.Repository
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private IOcelotConfiguration _ocelotConfiguration;
 | 
					        private IOcelotConfiguration _ocelotConfiguration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Response<IOcelotConfiguration> Get()
 | 
					        public async Task<Response<IOcelotConfiguration>> Get()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new OkResponse<IOcelotConfiguration>(_ocelotConfiguration);
 | 
					            return new OkResponse<IOcelotConfiguration>(_ocelotConfiguration);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Response AddOrReplace(IOcelotConfiguration ocelotConfiguration)
 | 
					        public async Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            lock (LockObject)
 | 
					            lock (LockObject)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					using Ocelot.Errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.Configuration.Repository
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class UnableToSetConfigInConsulError : Error
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public UnableToSetConfigInConsulError(string message) 
 | 
				
			||||||
 | 
					            : base(message, OcelotErrorCode.UnableToSetConfigInConsulError)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -33,7 +33,7 @@ namespace Ocelot.Configuration.Setter
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if(!config.IsError)
 | 
					            if(!config.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _configRepo.AddOrReplace(config.Data);
 | 
					                await _configRepo.AddOrReplace(config.Data);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new ErrorResponse(config.Errors);
 | 
					            return new ErrorResponse(config.Errors);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,24 +40,32 @@ using System.Collections.Generic;
 | 
				
			|||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Net.Http;
 | 
					using System.Net.Http;
 | 
				
			||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using Ocelot.Configuration;
 | 
				
			||||||
using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
 | 
					using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.DependencyInjection
 | 
					namespace Ocelot.DependencyInjection
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public static class ServiceCollectionExtensions
 | 
					    public static class ServiceCollectionExtensions
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static IServiceCollection AddOcelotOutputCaching(this IServiceCollection services, Action<ConfigurationBuilderCachePart> settings)
 | 
					        public static IServiceCollection AddOcelotStoreConfigurationInConsul(this IServiceCollection services, ConsulRegistryConfiguration consulConfig)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var cacheManagerOutputCache = CacheFactory.Build<HttpResponseMessage>("OcelotOutputCache", settings);
 | 
					            services.AddSingleton<ConsulRegistryConfiguration>(consulConfig);
 | 
				
			||||||
            var ocelotCacheManager = new OcelotCacheManagerCache<HttpResponseMessage>(cacheManagerOutputCache);
 | 
					            services.AddSingleton<IOcelotConfigurationRepository, ConsulOcelotConfigurationRepository>();
 | 
				
			||||||
            services.TryAddSingleton<ICacheManager<HttpResponseMessage>>(cacheManagerOutputCache);
 | 
					 | 
				
			||||||
            services.TryAddSingleton<IOcelotCache<HttpResponseMessage>>(ocelotCacheManager);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return services;
 | 
					            return services;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static IServiceCollection AddOcelot(this IServiceCollection services, IConfigurationRoot configurationRoot)
 | 
					        public static IServiceCollection AddOcelot(this IServiceCollection services, IConfigurationRoot configurationRoot, Action<ConfigurationBuilderCachePart> settings)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            var cacheManagerOutputCache = CacheFactory.Build<HttpResponseMessage>("OcelotOutputCache", settings);
 | 
				
			||||||
 | 
					            var ocelotOutputCacheManager = new OcelotCacheManagerCache<HttpResponseMessage>(cacheManagerOutputCache);
 | 
				
			||||||
 | 
					            services.TryAddSingleton<ICacheManager<HttpResponseMessage>>(cacheManagerOutputCache);
 | 
				
			||||||
 | 
					            services.TryAddSingleton<IOcelotCache<HttpResponseMessage>>(ocelotOutputCacheManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var ocelotConfigCacheManagerOutputCache = CacheFactory.Build<IOcelotConfiguration>("OcelotConfigurationCache", settings);
 | 
				
			||||||
 | 
					            var ocelotConfigCacheManager = new OcelotCacheManagerCache<IOcelotConfiguration>(ocelotConfigCacheManagerOutputCache);
 | 
				
			||||||
 | 
					            services.TryAddSingleton<ICacheManager<IOcelotConfiguration>>(ocelotConfigCacheManagerOutputCache);
 | 
				
			||||||
 | 
					            services.TryAddSingleton<IOcelotCache<IOcelotConfiguration>>(ocelotConfigCacheManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            services.Configure<FileConfiguration>(configurationRoot);
 | 
					            services.Configure<FileConfiguration>(configurationRoot);
 | 
				
			||||||
            services.TryAddSingleton<IOcelotConfigurationCreator, FileOcelotConfigurationCreator>();
 | 
					            services.TryAddSingleton<IOcelotConfigurationCreator, FileOcelotConfigurationCreator>();
 | 
				
			||||||
            services.TryAddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
 | 
					            services.TryAddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Ocelot.Configuration.Provider;
 | 
					using Ocelot.Configuration.Provider;
 | 
				
			||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
					using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
				
			||||||
using Ocelot.Errors;
 | 
					using Ocelot.Errors;
 | 
				
			||||||
@@ -21,9 +22,9 @@ namespace Ocelot.DownstreamRouteFinder.Finder
 | 
				
			|||||||
            _urlPathPlaceholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
 | 
					            _urlPathPlaceholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
 | 
					        public async Task<Response<DownstreamRoute>> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var configuration = _configProvider.Get();
 | 
					            var configuration = await _configProvider.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var applicableReRoutes = configuration.Data.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod.Method.ToLower(), upstreamHttpMethod.ToLower(), StringComparison.CurrentCultureIgnoreCase));
 | 
					            var applicableReRoutes = configuration.Data.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod.Method.ToLower(), upstreamHttpMethod.ToLower(), StringComparison.CurrentCultureIgnoreCase));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
using Ocelot.Responses;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.DownstreamRouteFinder.Finder
 | 
					namespace Ocelot.DownstreamRouteFinder.Finder
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public interface IDownstreamRouteFinder
 | 
					    public interface IDownstreamRouteFinder
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod);
 | 
					        Task<Response<DownstreamRoute>> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
 | 
					            _logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.Request.Method);
 | 
					            var downstreamRoute = await _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.Request.Method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (downstreamRoute.IsError)
 | 
					            if (downstreamRoute.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,7 @@
 | 
				
			|||||||
        UnableToFindServiceDiscoveryProviderError,
 | 
					        UnableToFindServiceDiscoveryProviderError,
 | 
				
			||||||
        UnableToFindLoadBalancerError,
 | 
					        UnableToFindLoadBalancerError,
 | 
				
			||||||
        RequestTimedOutError,
 | 
					        RequestTimedOutError,
 | 
				
			||||||
        UnableToFindQoSProviderError
 | 
					        UnableToFindQoSProviderError,
 | 
				
			||||||
 | 
					        UnableToSetConfigInConsulError
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -141,14 +141,19 @@ namespace Ocelot.Middleware
 | 
				
			|||||||
            
 | 
					            
 | 
				
			||||||
            var configProvider = (IOcelotConfigurationProvider)builder.ApplicationServices.GetService(typeof(IOcelotConfigurationProvider));
 | 
					            var configProvider = (IOcelotConfigurationProvider)builder.ApplicationServices.GetService(typeof(IOcelotConfigurationProvider));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var ocelotConfiguration = await configProvider.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                var config = await configSetter.Set(fileConfig.Value);
 | 
					                var config = await configSetter.Set(fileConfig.Value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(config == null || config.IsError)
 | 
					                if (config == null || config.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    throw new Exception("Unable to start Ocelot: configuration was not set up correctly.");
 | 
					                    throw new Exception("Unable to start Ocelot: configuration was not set up correctly.");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var ocelotConfiguration = configProvider.Get();
 | 
					            ocelotConfiguration = await configProvider.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError)
 | 
					            if(ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ namespace Ocelot.RateLimit.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var options = DownstreamRoute.ReRoute.RateLimitOptions;
 | 
					            var options = DownstreamRoute.ReRoute.RateLimitOptions;
 | 
				
			||||||
            // check if rate limiting is enabled
 | 
					            // check if rate limiting is enabled
 | 
				
			||||||
            if (!DownstreamRoute.ReRoute.EnableEndpointRateLimiting)
 | 
					            if (!DownstreamRoute.ReRoute.EnableEndpointEndpointRateLimiting)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"EndpointRateLimiting is not enabled for {DownstreamRoute.ReRoute.DownstreamPathTemplate}");
 | 
					                _logger.LogDebug($"EndpointRateLimiting is not enabled for {DownstreamRoute.ReRoute.DownstreamPathTemplate}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ namespace Ocelot.RateLimit
 | 
				
			|||||||
                if (entry.HasValue)
 | 
					                if (entry.HasValue)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // entry has not expired
 | 
					                    // entry has not expired
 | 
				
			||||||
                    if (entry.Value.Timestamp + rule.PeriodTimespan >= DateTime.UtcNow)
 | 
					                    if (entry.Value.Timestamp + TimeSpan.FromSeconds(rule.PeriodTimespan) >= DateTime.UtcNow)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // increment request count
 | 
					                        // increment request count
 | 
				
			||||||
                        var totalRequests = entry.Value.TotalRequests + 1;
 | 
					                        var totalRequests = entry.Value.TotalRequests + 1;
 | 
				
			||||||
@@ -45,7 +45,7 @@ namespace Ocelot.RateLimit
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                // stores: id (string) - timestamp (datetime) - total_requests (long)
 | 
					                // stores: id (string) - timestamp (datetime) - total_requests (long)
 | 
				
			||||||
                _counterHandler.Set(counterId, counter, rule.PeriodTimespan);
 | 
					                _counterHandler.Set(counterId, counter, TimeSpan.FromSeconds(rule.PeriodTimespan));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return counter;
 | 
					            return counter;
 | 
				
			||||||
@@ -95,7 +95,7 @@ namespace Ocelot.RateLimit
 | 
				
			|||||||
        public string RetryAfterFrom(DateTime timestamp, RateLimitRule rule)
 | 
					        public string RetryAfterFrom(DateTime timestamp, RateLimitRule rule)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var secondsPast = Convert.ToInt32((DateTime.UtcNow - timestamp).TotalSeconds);
 | 
					            var secondsPast = Convert.ToInt32((DateTime.UtcNow - timestamp).TotalSeconds);
 | 
				
			||||||
            var retryAfter = Convert.ToInt32(rule.PeriodTimespan.TotalSeconds);
 | 
					            var retryAfter = Convert.ToInt32(TimeSpan.FromSeconds(rule.PeriodTimespan).TotalSeconds);
 | 
				
			||||||
            retryAfter = retryAfter > 1 ? retryAfter - secondsPast : 1;
 | 
					            retryAfter = retryAfter > 1 ? retryAfter - secondsPast : 1;
 | 
				
			||||||
            return retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
 | 
					            return retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,15 +57,15 @@ namespace Ocelot.Requester.QoS
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<PollyQoSProvider>();
 | 
					            _logger = loggerFactory.CreateLogger<PollyQoSProvider>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _timeoutPolicy = Policy.TimeoutAsync(reRoute.QosOptions.TimeoutValue, reRoute.QosOptions.TimeoutStrategy);
 | 
					            _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.TimeoutValue), reRoute.QosOptionsOptions.TimeoutStrategy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _circuitBreakerPolicy = Policy
 | 
					            _circuitBreakerPolicy = Policy
 | 
				
			||||||
                .Handle<HttpRequestException>()
 | 
					                .Handle<HttpRequestException>()
 | 
				
			||||||
                .Or<TimeoutRejectedException>()
 | 
					                .Or<TimeoutRejectedException>()
 | 
				
			||||||
                .Or<TimeoutException>()
 | 
					                .Or<TimeoutException>()
 | 
				
			||||||
                .CircuitBreakerAsync(
 | 
					                .CircuitBreakerAsync(
 | 
				
			||||||
                    exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking,
 | 
					                    exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking,
 | 
				
			||||||
                    durationOfBreak: reRoute.QosOptions.DurationOfBreak,
 | 
					                    durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak),
 | 
				
			||||||
                    onBreak: (ex, breakDelay) =>
 | 
					                    onBreak: (ex, breakDelay) =>
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        _logger.LogError(
 | 
					                        _logger.LogError(
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										171
									
								
								test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using Consul;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using Ocelot.Configuration;
 | 
				
			||||||
 | 
					using Ocelot.Configuration.File;
 | 
				
			||||||
 | 
					using Ocelot.Configuration.Repository;
 | 
				
			||||||
 | 
					using Ocelot.ServiceDiscovery;
 | 
				
			||||||
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.AcceptanceTests
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class ConfigurationInConsul : IDisposable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private IWebHost _builder;
 | 
				
			||||||
 | 
					        private readonly Steps _steps;
 | 
				
			||||||
 | 
					        private IWebHost _fakeConsulBuilder;
 | 
				
			||||||
 | 
					        private IOcelotConfiguration _config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ConfigurationInConsul()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _steps = new Steps();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_return_response_200_with_simple_url()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var configuration = new FileConfiguration
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ReRoutes = new List<FileReRoute>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        new FileReRoute
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            DownstreamPathTemplate = "/",
 | 
				
			||||||
 | 
					                            DownstreamScheme = "http",
 | 
				
			||||||
 | 
					                            DownstreamHost = "localhost",
 | 
				
			||||||
 | 
					                            DownstreamPort = 51779,
 | 
				
			||||||
 | 
					                            UpstreamPathTemplate = "/",
 | 
				
			||||||
 | 
					                            UpstreamHttpMethod = "Get",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                GlobalConfiguration = new FileGlobalConfiguration()
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Provider = "Consul",
 | 
				
			||||||
 | 
					                        Host = "localhost",
 | 
				
			||||||
 | 
					                        Port = 9500
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var fakeConsulServiceDiscoveryUrl = "http://localhost:9500";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl))
 | 
				
			||||||
 | 
					                .And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", 200, "Hello from Laura"))
 | 
				
			||||||
 | 
					                .And(x => _steps.GivenThereIsAConfiguration(configuration))
 | 
				
			||||||
 | 
					                .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig))
 | 
				
			||||||
 | 
					                .When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
 | 
				
			||||||
 | 
					                .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
				
			||||||
 | 
					                .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _fakeConsulBuilder = new WebHostBuilder()
 | 
				
			||||||
 | 
					                            .UseUrls(url)
 | 
				
			||||||
 | 
					                            .UseKestrel()
 | 
				
			||||||
 | 
					                            .UseContentRoot(Directory.GetCurrentDirectory())
 | 
				
			||||||
 | 
					                            .UseIISIntegration()
 | 
				
			||||||
 | 
					                            .UseUrls(url)
 | 
				
			||||||
 | 
					                            .Configure(app =>
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                app.Run(async context =>
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration")
 | 
				
			||||||
 | 
					                                    {
 | 
				
			||||||
 | 
					                                        var json = JsonConvert.SerializeObject(_config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        var bytes = Encoding.UTF8.GetBytes(json);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        var base64 = Convert.ToBase64String(bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        var kvp = new FakeConsulGetResponse(base64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        await context.Response.WriteJsonAsync(new FakeConsulGetResponse[]{kvp});
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                    else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration")
 | 
				
			||||||
 | 
					                                    {
 | 
				
			||||||
 | 
					                                        try
 | 
				
			||||||
 | 
					                                        {
 | 
				
			||||||
 | 
					                                            var reader = new StreamReader(context.Request.Body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                            var json = reader.ReadToEnd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                            _config = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                            var response = JsonConvert.SerializeObject(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                            await context.Response.WriteAsync(response);
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        catch (Exception e)
 | 
				
			||||||
 | 
					                                        {
 | 
				
			||||||
 | 
					                                            Console.WriteLine(e);
 | 
				
			||||||
 | 
					                                            throw;
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                });
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                            .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _fakeConsulBuilder.Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public class FakeConsulGetResponse
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public FakeConsulGetResponse(string value)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Value = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public int CreateIndex => 100;
 | 
				
			||||||
 | 
					            public int ModifyIndex => 200;
 | 
				
			||||||
 | 
					            public int LockIndex => 200;
 | 
				
			||||||
 | 
					            public string Key => "OcelotConfiguration";
 | 
				
			||||||
 | 
					            public int Flags => 0;
 | 
				
			||||||
 | 
					            public string Value { get; private set; }
 | 
				
			||||||
 | 
					            public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _builder = new WebHostBuilder()
 | 
				
			||||||
 | 
					                .UseUrls(url)
 | 
				
			||||||
 | 
					                .UseKestrel()
 | 
				
			||||||
 | 
					                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
				
			||||||
 | 
					                .UseIISIntegration()
 | 
				
			||||||
 | 
					                .UseUrls(url)
 | 
				
			||||||
 | 
					                .Configure(app =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    app.Run(async context =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        context.Response.StatusCode = statusCode;
 | 
				
			||||||
 | 
					                        await context.Response.WriteAsync(responseBody);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _builder.Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _builder?.Dispose();
 | 
				
			||||||
 | 
					            _steps.Dispose();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -15,9 +15,11 @@ using Microsoft.Extensions.DependencyInjection;
 | 
				
			|||||||
using Microsoft.Extensions.Logging;
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
using Newtonsoft.Json;
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
using Ocelot.Configuration.File;
 | 
					using Ocelot.Configuration.File;
 | 
				
			||||||
 | 
					using Ocelot.Configuration.Repository;
 | 
				
			||||||
using Ocelot.DependencyInjection;
 | 
					using Ocelot.DependencyInjection;
 | 
				
			||||||
using Ocelot.ManualTest;
 | 
					using Ocelot.ManualTest;
 | 
				
			||||||
using Ocelot.Middleware;
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
 | 
					using Ocelot.ServiceDiscovery;
 | 
				
			||||||
using Shouldly;
 | 
					using Shouldly;
 | 
				
			||||||
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
 | 
					using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,6 +86,22 @@ namespace Ocelot.AcceptanceTests
 | 
				
			|||||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
					            _ocelotClient = _ocelotServer.CreateClient();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void GivenOcelotIsRunningUsingConsulToStoreConfig(ConsulRegistryConfiguration consulConfig)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _webHostBuilder = new WebHostBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _webHostBuilder.ConfigureServices(s =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                s.AddSingleton(_webHostBuilder);
 | 
				
			||||||
 | 
					                s.AddOcelotStoreConfigurationInConsul(consulConfig);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _ocelotServer = new TestServer(_webHostBuilder
 | 
				
			||||||
 | 
					                .UseStartup<Startup>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _ocelotClient = _ocelotServer.CreateClient();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal void ThenTheResponseShouldBe(FileConfiguration expected)
 | 
					        internal void ThenTheResponseShouldBe(FileConfiguration expected)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
 | 
					            var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
 | 
				
			||||||
@@ -138,8 +156,7 @@ namespace Ocelot.AcceptanceTests
 | 
				
			|||||||
                        .WithDictionaryHandle();
 | 
					                        .WithDictionaryHandle();
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    s.AddOcelotOutputCaching(settings);
 | 
					                    s.AddOcelot(configuration, settings);
 | 
				
			||||||
                    s.AddOcelot(configuration);
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .ConfigureLogging(l =>
 | 
					                .ConfigureLogging(l =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,8 +37,8 @@ namespace Ocelot.ManualTest
 | 
				
			|||||||
                })
 | 
					                })
 | 
				
			||||||
                .WithDictionaryHandle();
 | 
					                .WithDictionaryHandle();
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            services.AddOcelotOutputCaching(settings);
 | 
					
 | 
				
			||||||
            services.AddOcelot(Configuration);
 | 
					            services.AddOcelot(Configuration, settings);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 | 
					        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -690,10 +690,10 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void ThenTheQosOptionsAre(QoSOptions qosOptions)
 | 
					        private void ThenTheQosOptionsAre(QoSOptions qosOptions)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _config.Data.ReRoutes[0].QosOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
 | 
					            _config.Data.ReRoutes[0].QosOptionsOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _config.Data.ReRoutes[0].QosOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
 | 
					            _config.Data.ReRoutes[0].QosOptionsOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
 | 
				
			||||||
            _config.Data.ReRoutes[0].QosOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
 | 
					            _config.Data.ReRoutes[0].QosOptionsOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void WhenIGetTheConfiguration()
 | 
					        private void WhenIGetTheConfiguration()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _getResult = _repo.Get();
 | 
					            _getResult = _repo.Get().Result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenThereIsASavedConfiguration()
 | 
					        private void GivenThereIsASavedConfiguration()
 | 
				
			||||||
@@ -65,7 +65,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void WhenIAddOrReplaceTheConfig()
 | 
					        private void WhenIAddOrReplaceTheConfig()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _result = _repo.AddOrReplace(_config);
 | 
					            _result = _repo.AddOrReplace(_config).Result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenNoErrorsAreReturned()
 | 
					        private void ThenNoErrorsAreReturned()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,12 +53,12 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            _configurationRepository
 | 
					            _configurationRepository
 | 
				
			||||||
                .Setup(x => x.Get())
 | 
					                .Setup(x => x.Get())
 | 
				
			||||||
                .Returns(config);
 | 
					                .ReturnsAsync(config);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void WhenIGetTheConfig()
 | 
					        private void WhenIGetTheConfig()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _result = _ocelotConfigurationProvider.Get();
 | 
					            _result = _ocelotConfigurationProvider.Get().Result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void TheFollowingIsReturned(Response<IOcelotConfiguration> expected)
 | 
					        private void TheFollowingIsReturned(Response<IOcelotConfiguration> expected)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
                .WithQuotaExceededMessage("QuotaExceededMessage")
 | 
					                .WithQuotaExceededMessage("QuotaExceededMessage")
 | 
				
			||||||
                .WithRateLimitCounterPrefix("RateLimitCounterPrefix")
 | 
					                .WithRateLimitCounterPrefix("RateLimitCounterPrefix")
 | 
				
			||||||
                .WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
 | 
					                .WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
 | 
				
			||||||
                       TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan),
 | 
					                       fileReRoute.RateLimitOptions.PeriodTimespan,
 | 
				
			||||||
                       fileReRoute.RateLimitOptions.Limit))
 | 
					                       fileReRoute.RateLimitOptions.Limit))
 | 
				
			||||||
                .Build();
 | 
					                .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,7 +102,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
            _result.RateLimitCounterPrefix.ShouldBe(expected.RateLimitCounterPrefix);
 | 
					            _result.RateLimitCounterPrefix.ShouldBe(expected.RateLimitCounterPrefix);
 | 
				
			||||||
            _result.RateLimitRule.Limit.ShouldBe(expected.RateLimitRule.Limit);
 | 
					            _result.RateLimitRule.Limit.ShouldBe(expected.RateLimitRule.Limit);
 | 
				
			||||||
            _result.RateLimitRule.Period.ShouldBe(expected.RateLimitRule.Period);
 | 
					            _result.RateLimitRule.Period.ShouldBe(expected.RateLimitRule.Period);
 | 
				
			||||||
            _result.RateLimitRule.PeriodTimespan.Ticks.ShouldBe(expected.RateLimitRule.PeriodTimespan.Ticks);
 | 
					            TimeSpan.FromSeconds(_result.RateLimitRule.PeriodTimespan).Ticks.ShouldBe(TimeSpan.FromSeconds(expected.RateLimitRule.PeriodTimespan).Ticks);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
				
			|||||||
            _downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
 | 
					            _downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
 | 
				
			||||||
            _downstreamRouteFinder
 | 
					            _downstreamRouteFinder
 | 
				
			||||||
                .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>()))
 | 
					                .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>()))
 | 
				
			||||||
                .Returns(_downstreamRoute);
 | 
					                .ReturnsAsync(_downstreamRoute);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Dispose()
 | 
					        public void Dispose()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -199,7 +199,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
				
			|||||||
            _reRoutesConfig = reRoutesConfig;
 | 
					            _reRoutesConfig = reRoutesConfig;
 | 
				
			||||||
            _mockConfig
 | 
					            _mockConfig
 | 
				
			||||||
                .Setup(x => x.Get())
 | 
					                .Setup(x => x.Get())
 | 
				
			||||||
                .Returns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath)));
 | 
					                .ReturnsAsync(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
 | 
					        private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
 | 
				
			||||||
@@ -209,7 +209,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void WhenICallTheFinder()
 | 
					        private void WhenICallTheFinder()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod);
 | 
					            _result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod).Result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenTheFollowingIsReturned(DownstreamRoute expected)
 | 
					        private void ThenTheFollowingIsReturned(DownstreamRoute expected)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ namespace Ocelot.UnitTests.RateLimit
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
 | 
					            var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
 | 
				
			||||||
                 new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
 | 
					                 new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
 | 
				
			||||||
                     new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", TimeSpan.FromSeconds(100), 3), 429))
 | 
					                     new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", 100, 3), 429))
 | 
				
			||||||
                     .WithUpstreamHttpMethod("Get")
 | 
					                     .WithUpstreamHttpMethod("Get")
 | 
				
			||||||
                     .Build());
 | 
					                     .Build());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.RateLimit
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
 | 
					            var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
 | 
				
			||||||
                 new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
 | 
					                 new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
 | 
				
			||||||
                     new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new  RateLimitRule( "1s", TimeSpan.FromSeconds(100),3),429))
 | 
					                     new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new  RateLimitRule( "1s", 100,3),429))
 | 
				
			||||||
                     .WithUpstreamHttpMethod("Get")
 | 
					                     .WithUpstreamHttpMethod("Get")
 | 
				
			||||||
                     .Build());
 | 
					                     .Build());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user