mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	started implementing the consul service provider
This commit is contained in:
		@@ -34,6 +34,8 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
        private string _downstreamHost;
 | 
			
		||||
        private int _dsPort;
 | 
			
		||||
        private string _loadBalancer;
 | 
			
		||||
        private string _serviceProviderHost;
 | 
			
		||||
        private int _serviceProviderPort;
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder()
 | 
			
		||||
        {
 | 
			
		||||
@@ -206,14 +208,25 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithServiceProviderHost(string serviceProviderHost)
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProviderHost = serviceProviderHost;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithServiceProviderPort(int serviceProviderPort)
 | 
			
		||||
        {
 | 
			
		||||
            _serviceProviderPort = serviceProviderPort;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRoute Build()
 | 
			
		||||
        {
 | 
			
		||||
            return new ReRoute(new DownstreamPathTemplate(_downstreamPathTemplate), _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, 
 | 
			
		||||
                _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, 
 | 
			
		||||
                _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement, 
 | 
			
		||||
                _isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName, 
 | 
			
		||||
                _useServiceDiscovery, _serviceDiscoveryAddress, _serviceDiscoveryProvider, _downstreamScheme, _loadBalancer,
 | 
			
		||||
                _downstreamHost, _dsPort, _loadBalancerKey);
 | 
			
		||||
                _isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _downstreamScheme, _loadBalancer,
 | 
			
		||||
                _downstreamHost, _dsPort, _loadBalancerKey, new ServiceProviderConfiguraion(_serviceName, _downstreamHost, _dsPort, _useServiceDiscovery, _serviceDiscoveryProvider, _serviceProviderHost, _serviceProviderPort));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
@@ -8,7 +9,6 @@ using Ocelot.Configuration.Parser;
 | 
			
		||||
using Ocelot.Configuration.Validator;
 | 
			
		||||
using Ocelot.LoadBalancer.LoadBalancers;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.ServiceDiscovery;
 | 
			
		||||
using Ocelot.Utilities;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
@@ -46,9 +46,9 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
            _logger = logger;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<IOcelotConfiguration> Create()
 | 
			
		||||
        public async Task<Response<IOcelotConfiguration>> Create()
 | 
			
		||||
        {     
 | 
			
		||||
            var config = SetUpConfiguration();
 | 
			
		||||
            var config = await SetUpConfiguration();
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<IOcelotConfiguration>(config);
 | 
			
		||||
        }
 | 
			
		||||
@@ -57,7 +57,7 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
        /// This method is meant to be tempoary to convert a config to an ocelot config...probably wont keep this but we will see
 | 
			
		||||
        /// will need a refactor at some point as its crap
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private IOcelotConfiguration SetUpConfiguration()
 | 
			
		||||
        private async Task<IOcelotConfiguration> SetUpConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            var response = _configurationValidator.IsValid(_options.Value);
 | 
			
		||||
 | 
			
		||||
@@ -77,14 +77,14 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
 | 
			
		||||
            foreach (var reRoute in _options.Value.ReRoutes)
 | 
			
		||||
            {
 | 
			
		||||
                var ocelotReRoute = SetUpReRoute(reRoute, _options.Value.GlobalConfiguration);
 | 
			
		||||
                var ocelotReRoute = await SetUpReRoute(reRoute, _options.Value.GlobalConfiguration);
 | 
			
		||||
                reRoutes.Add(ocelotReRoute);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            return new OcelotConfiguration(reRoutes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private ReRoute SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
 | 
			
		||||
        private async Task<ReRoute> SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var globalRequestIdConfiguration = !string.IsNullOrEmpty(globalConfiguration?.RequestIdKey);
 | 
			
		||||
 | 
			
		||||
@@ -101,7 +101,6 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
                : fileReRoute.RequestIdKey;
 | 
			
		||||
 | 
			
		||||
            var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName)
 | 
			
		||||
                && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address)
 | 
			
		||||
                && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
 | 
			
		||||
 | 
			
		||||
            //note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
 | 
			
		||||
@@ -109,6 +108,13 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
 | 
			
		||||
            ReRoute reRoute;
 | 
			
		||||
 | 
			
		||||
            var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
 | 
			
		||||
 | 
			
		||||
            var serviceProviderConfiguration = new ServiceProviderConfiguraion(fileReRoute.ServiceName,
 | 
			
		||||
                fileReRoute.DownstreamHost, fileReRoute.DownstreamPort, useServiceDiscovery,
 | 
			
		||||
                globalConfiguration?.ServiceDiscoveryProvider?.Provider, globalConfiguration?.ServiceDiscoveryProvider?.Host,
 | 
			
		||||
                serviceProviderPort);
 | 
			
		||||
 | 
			
		||||
            if (isAuthenticated)
 | 
			
		||||
            {
 | 
			
		||||
                var authOptionsForRoute = new AuthenticationOptions(fileReRoute.AuthenticationOptions.Provider,
 | 
			
		||||
@@ -125,11 +131,10 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
                    fileReRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated,
 | 
			
		||||
                    authOptionsForRoute, claimsToHeaders, claimsToClaims,
 | 
			
		||||
                    fileReRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries,
 | 
			
		||||
                    requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds),
 | 
			
		||||
                    fileReRoute.ServiceName, useServiceDiscovery,
 | 
			
		||||
                    globalConfiguration?.ServiceDiscoveryProvider?.Provider,
 | 
			
		||||
                    globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme,
 | 
			
		||||
                    fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort, loadBalancerKey);
 | 
			
		||||
                    requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds)
 | 
			
		||||
                    , fileReRoute.DownstreamScheme,
 | 
			
		||||
                    fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort, loadBalancerKey,
 | 
			
		||||
                    serviceProviderConfiguration);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -139,13 +144,12 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
                    null, new List<ClaimToThing>(), new List<ClaimToThing>(),
 | 
			
		||||
                    fileReRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>(),
 | 
			
		||||
                    requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds),
 | 
			
		||||
                    fileReRoute.ServiceName, useServiceDiscovery,
 | 
			
		||||
                    globalConfiguration?.ServiceDiscoveryProvider?.Provider,
 | 
			
		||||
                    globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme,
 | 
			
		||||
                    fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort, loadBalancerKey);
 | 
			
		||||
                    fileReRoute.DownstreamScheme,
 | 
			
		||||
                    fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort, loadBalancerKey,
 | 
			
		||||
                    serviceProviderConfiguration);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var loadBalancer = _loadBalanceFactory.Get(reRoute);
 | 
			
		||||
            var loadBalancer = await _loadBalanceFactory.Get(reRoute);
 | 
			
		||||
            _loadBalancerHouse.Add(reRoute.LoadBalancerKey, loadBalancer);
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Creator
 | 
			
		||||
{
 | 
			
		||||
    public interface IOcelotConfigurationCreator
 | 
			
		||||
    {
 | 
			
		||||
        Response<IOcelotConfiguration> Create();
 | 
			
		||||
        Task<Response<IOcelotConfiguration>> Create();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@ namespace Ocelot.Configuration.File
 | 
			
		||||
    public class FileServiceDiscoveryProvider
 | 
			
		||||
    {
 | 
			
		||||
        public string Provider {get;set;}
 | 
			
		||||
        public string Address {get;set;}
 | 
			
		||||
        public string Host {get;set;}
 | 
			
		||||
        public int Port { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Provider
 | 
			
		||||
{
 | 
			
		||||
    public interface IOcelotConfigurationProvider
 | 
			
		||||
    {
 | 
			
		||||
        Response<IOcelotConfiguration> Get();
 | 
			
		||||
        Task<Response<IOcelotConfiguration>> Get();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.Repository;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
@@ -19,7 +20,7 @@ namespace Ocelot.Configuration.Provider
 | 
			
		||||
            _creator = creator;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<IOcelotConfiguration> Get()
 | 
			
		||||
        public async Task<Response<IOcelotConfiguration>> Get()
 | 
			
		||||
        {
 | 
			
		||||
            var repoConfig = _repo.Get();
 | 
			
		||||
 | 
			
		||||
@@ -30,7 +31,7 @@ namespace Ocelot.Configuration.Provider
 | 
			
		||||
 | 
			
		||||
            if (repoConfig.Data == null)
 | 
			
		||||
            {
 | 
			
		||||
                var creatorConfig = _creator.Create();
 | 
			
		||||
                var creatorConfig = await _creator.Create();
 | 
			
		||||
 | 
			
		||||
                if (creatorConfig.IsError)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,15 +6,20 @@ namespace Ocelot.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class ReRoute
 | 
			
		||||
    {
 | 
			
		||||
        public ReRoute(DownstreamPathTemplate downstreamPathTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, 
 | 
			
		||||
            bool isAuthenticated, AuthenticationOptions authenticationOptions, List<ClaimToThing> configurationHeaderExtractorProperties, 
 | 
			
		||||
            List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries, 
 | 
			
		||||
            string requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery,
 | 
			
		||||
            string serviceDiscoveryProvider, string serviceDiscoveryAddress,
 | 
			
		||||
            string downstreamScheme, string loadBalancer, string downstreamHost, int downstreamPort, 
 | 
			
		||||
            string loadBalancerKey)
 | 
			
		||||
        public ReRoute(DownstreamPathTemplate downstreamPathTemplate, 
 | 
			
		||||
            string upstreamTemplate, string upstreamHttpMethod, 
 | 
			
		||||
            string upstreamTemplatePattern, 
 | 
			
		||||
            bool isAuthenticated, AuthenticationOptions authenticationOptions, 
 | 
			
		||||
            List<ClaimToThing> configurationHeaderExtractorProperties, 
 | 
			
		||||
            List<ClaimToThing> claimsToClaims, 
 | 
			
		||||
            Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, 
 | 
			
		||||
            List<ClaimToThing> claimsToQueries, 
 | 
			
		||||
            string requestIdKey, bool isCached, CacheOptions fileCacheOptions, 
 | 
			
		||||
            string downstreamScheme, string loadBalancer, string downstreamHost, 
 | 
			
		||||
            int downstreamPort, string loadBalancerKey, ServiceProviderConfiguraion serviceProviderConfiguraion)
 | 
			
		||||
        {
 | 
			
		||||
            LoadBalancerKey = loadBalancerKey;
 | 
			
		||||
            ServiceProviderConfiguraion = serviceProviderConfiguraion;
 | 
			
		||||
            LoadBalancer = loadBalancer;
 | 
			
		||||
            DownstreamHost = downstreamHost;
 | 
			
		||||
            DownstreamPort = downstreamPort;
 | 
			
		||||
@@ -35,12 +40,9 @@ namespace Ocelot.Configuration
 | 
			
		||||
                ?? new List<ClaimToThing>();
 | 
			
		||||
            ClaimsToHeaders = configurationHeaderExtractorProperties 
 | 
			
		||||
                ?? new List<ClaimToThing>();
 | 
			
		||||
                ServiceName = serviceName;
 | 
			
		||||
                UseServiceDiscovery = useServiceDiscovery;
 | 
			
		||||
                ServiceDiscoveryProvider = serviceDiscoveryProvider;
 | 
			
		||||
                ServiceDiscoveryAddress = serviceDiscoveryAddress;
 | 
			
		||||
                DownstreamScheme = downstreamScheme;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string LoadBalancerKey {get;private set;}
 | 
			
		||||
        public DownstreamPathTemplate DownstreamPathTemplate { get; private set; }
 | 
			
		||||
        public string UpstreamTemplate { get; private set; }
 | 
			
		||||
@@ -56,13 +58,10 @@ namespace Ocelot.Configuration
 | 
			
		||||
        public string RequestIdKey { get; private set; }
 | 
			
		||||
        public bool IsCached { get; private set; }
 | 
			
		||||
        public CacheOptions FileCacheOptions { get; private set; }
 | 
			
		||||
        public string ServiceName { get; private set;}
 | 
			
		||||
        public bool UseServiceDiscovery { get; private set;}
 | 
			
		||||
        public string ServiceDiscoveryProvider { get; private set;}
 | 
			
		||||
        public string ServiceDiscoveryAddress { get; private set;}
 | 
			
		||||
        public string DownstreamScheme {get;private set;}
 | 
			
		||||
        public string LoadBalancer {get;private set;}
 | 
			
		||||
        public string DownstreamHost { get; private set; }
 | 
			
		||||
        public int DownstreamPort { get; private set; }
 | 
			
		||||
        public ServiceProviderConfiguraion ServiceProviderConfiguraion { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +1,25 @@
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
namespace Ocelot.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class ServiceProviderConfiguraion
 | 
			
		||||
    {
 | 
			
		||||
        public ServiceProviderConfiguraion(string serviceName, string downstreamHost, 
 | 
			
		||||
        int downstreamPort, bool useServiceDiscovery, string serviceDiscoveryProvider)
 | 
			
		||||
        public ServiceProviderConfiguraion(string serviceName, string downstreamHost,
 | 
			
		||||
            int downstreamPort, bool useServiceDiscovery, string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort)
 | 
			
		||||
        {
 | 
			
		||||
            ServiceName = serviceName;
 | 
			
		||||
            DownstreamHost = downstreamHost;
 | 
			
		||||
            DownstreamPort = downstreamPort;
 | 
			
		||||
            UseServiceDiscovery = useServiceDiscovery;
 | 
			
		||||
            ServiceDiscoveryProvider = serviceDiscoveryProvider;
 | 
			
		||||
            ServiceProviderHost = serviceProviderHost;
 | 
			
		||||
            ServiceProviderPort = serviceProviderPort;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string ServiceName { get; }
 | 
			
		||||
        public string DownstreamHost { get; }
 | 
			
		||||
        public int DownstreamPort { get; }
 | 
			
		||||
        public bool UseServiceDiscovery { get; }
 | 
			
		||||
        public string ServiceDiscoveryProvider {get;}
 | 
			
		||||
        public string ServiceDiscoveryProvider { get; }
 | 
			
		||||
        public string ServiceProviderHost { get; private set; }
 | 
			
		||||
        public int ServiceProviderPort { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
@@ -21,9 +22,9 @@ namespace Ocelot.DownstreamRouteFinder.Finder
 | 
			
		||||
            _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, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.DownstreamRouteFinder.Finder
 | 
			
		||||
{
 | 
			
		||||
    public interface IDownstreamRouteFinder
 | 
			
		||||
    {
 | 
			
		||||
        Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod);
 | 
			
		||||
        Task<Response<DownstreamRoute>> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
			
		||||
 | 
			
		||||
            _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)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/Ocelot/Infrastructure/Extensions/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/Ocelot/Infrastructure/Extensions/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Infrastructure.Extensions
 | 
			
		||||
{
 | 
			
		||||
    public static class StringExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static string TrimStart(this string source, string trim, StringComparison stringComparison = StringComparison.Ordinal)
 | 
			
		||||
        {
 | 
			
		||||
            if (source == null)
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            string s = source;
 | 
			
		||||
            while (s.StartsWith(trim, stringComparison))
 | 
			
		||||
            {
 | 
			
		||||
                s = s.Substring(trim.Length);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return s;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
@@ -6,7 +7,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
{
 | 
			
		||||
    public interface ILoadBalancer
 | 
			
		||||
    {
 | 
			
		||||
        Response<HostAndPort> Lease();
 | 
			
		||||
        Task<Response<HostAndPort>> Lease();
 | 
			
		||||
        Response Release(HostAndPort hostAndPort);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
{
 | 
			
		||||
    public interface ILoadBalancerFactory
 | 
			
		||||
    {
 | 
			
		||||
        ILoadBalancer Get(ReRoute reRoute);
 | 
			
		||||
        Task<ILoadBalancer> Get(ReRoute reRoute);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
@@ -9,20 +10,20 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
{
 | 
			
		||||
    public class LeastConnectionLoadBalancer : ILoadBalancer
 | 
			
		||||
    {
 | 
			
		||||
        private Func<List<Service>> _services;
 | 
			
		||||
        private List<Lease> _leases;
 | 
			
		||||
        private string _serviceName;
 | 
			
		||||
        private readonly Func<Task<List<Service>>> _services;
 | 
			
		||||
        private readonly List<Lease> _leases;
 | 
			
		||||
        private readonly string _serviceName;
 | 
			
		||||
 | 
			
		||||
        public LeastConnectionLoadBalancer(Func<List<Service>> services, string serviceName)
 | 
			
		||||
        public LeastConnectionLoadBalancer(Func<Task<List<Service>>> services, string serviceName)
 | 
			
		||||
        {
 | 
			
		||||
            _services = services;
 | 
			
		||||
            _serviceName = serviceName;
 | 
			
		||||
            _leases = new List<Lease>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<HostAndPort> Lease()
 | 
			
		||||
        public async Task<Response<HostAndPort>> Lease()
 | 
			
		||||
        {
 | 
			
		||||
            var services = _services();
 | 
			
		||||
            var services = await _services.Invoke();
 | 
			
		||||
 | 
			
		||||
            if (services == null)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.ServiceDiscovery;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
@@ -11,25 +12,27 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
            _serviceProviderFactory = serviceProviderFactory;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ILoadBalancer Get(ReRoute reRoute)
 | 
			
		||||
        public async Task<ILoadBalancer> Get(ReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            var serviceConfig = new ServiceProviderConfiguraion(
 | 
			
		||||
                reRoute.ServiceName,
 | 
			
		||||
                reRoute.DownstreamHost,
 | 
			
		||||
                reRoute.DownstreamPort,
 | 
			
		||||
                reRoute.UseServiceDiscovery,
 | 
			
		||||
                reRoute.ServiceDiscoveryProvider);
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.ServiceName,
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.DownstreamHost,
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.DownstreamPort,
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.UseServiceDiscovery,
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.ServiceDiscoveryProvider,
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.ServiceProviderHost,
 | 
			
		||||
                reRoute.ServiceProviderConfiguraion.ServiceProviderPort);
 | 
			
		||||
            
 | 
			
		||||
            var serviceProvider = _serviceProviderFactory.Get(serviceConfig);
 | 
			
		||||
 | 
			
		||||
            switch (reRoute.LoadBalancer)
 | 
			
		||||
            {
 | 
			
		||||
                case "RoundRobin":
 | 
			
		||||
                    return new RoundRobinLoadBalancer(serviceProvider.Get());
 | 
			
		||||
                    return new RoundRobinLoadBalancer(await serviceProvider.Get());
 | 
			
		||||
                case "LeastConnection":
 | 
			
		||||
                    return new LeastConnectionLoadBalancer(() => serviceProvider.Get(), reRoute.ServiceName);
 | 
			
		||||
                    return new LeastConnectionLoadBalancer(async () => await serviceProvider.Get(), reRoute.ServiceProviderConfiguraion.ServiceName);
 | 
			
		||||
                default:
 | 
			
		||||
                    return new NoLoadBalancer(serviceProvider.Get());
 | 
			
		||||
                    return new NoLoadBalancer(await serviceProvider.Get());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
@@ -14,7 +15,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
            _services = services;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<HostAndPort> Lease()
 | 
			
		||||
        public async Task<Response<HostAndPort>> Lease()
 | 
			
		||||
        {
 | 
			
		||||
            var service = _services.FirstOrDefault();
 | 
			
		||||
            return new OkResponse<HostAndPort>(service.HostAndPort);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
@@ -14,7 +15,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
            _services = services;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<HostAndPort> Lease()
 | 
			
		||||
        public async Task<Response<HostAndPort>> Lease()
 | 
			
		||||
        {
 | 
			
		||||
            if (_last >= _services.Count)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
			
		||||
                //set errors and return
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var hostAndPort = loadBalancer.Data.Lease();
 | 
			
		||||
            var hostAndPort = await loadBalancer.Data.Lease();
 | 
			
		||||
            if(hostAndPort.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                //set errors and return
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,19 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
    
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
{
 | 
			
		||||
    public class ConfigurationServiceProvider : IServiceDiscoveryProvider
 | 
			
		||||
    {
 | 
			
		||||
        private List<Service> _services;
 | 
			
		||||
        private readonly List<Service> _services;
 | 
			
		||||
 | 
			
		||||
        public ConfigurationServiceProvider(List<Service> services)
 | 
			
		||||
        {
 | 
			
		||||
            _services = services;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<Service> Get()
 | 
			
		||||
        public async Task<List<Service>> Get()
 | 
			
		||||
        {
 | 
			
		||||
            return _services;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								src/Ocelot/ServiceDiscovery/ConsulRegistryConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Ocelot/ServiceDiscovery/ConsulRegistryConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
{
 | 
			
		||||
    public class ConsulRegistryConfiguration
 | 
			
		||||
    {
 | 
			
		||||
        public ConsulRegistryConfiguration(string hostName, int port, string serviceName)
 | 
			
		||||
        {
 | 
			
		||||
            HostName = hostName;
 | 
			
		||||
            Port = port;
 | 
			
		||||
            ServiceName = serviceName;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string ServiceName { get; private set; }
 | 
			
		||||
        public string HostName { get; private set; }
 | 
			
		||||
        public int Port { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,15 +2,54 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Ocelot.Infrastructure.Extensions;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
{
 | 
			
		||||
    public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
 | 
			
		||||
    {
 | 
			
		||||
        public List<Service> Get()
 | 
			
		||||
        private readonly ConsulRegistryConfiguration _configuration;
 | 
			
		||||
        private readonly ConsulClient _consul;
 | 
			
		||||
        private const string VersionPrefix = "version-";
 | 
			
		||||
 | 
			
		||||
        public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration consulRegistryConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
            var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName;
 | 
			
		||||
            var consulPort = consulRegistryConfiguration?.Port ?? 8500;
 | 
			
		||||
            _configuration = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.ServiceName);
 | 
			
		||||
 | 
			
		||||
            _consul = new ConsulClient(config =>
 | 
			
		||||
            {
 | 
			
		||||
                config.Address = new Uri($"http://{_configuration.HostName}:{_configuration.Port}");
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<List<Service>> Get()
 | 
			
		||||
        {
 | 
			
		||||
            var queryResult = await _consul.Health.Service(_configuration.ServiceName, string.Empty, true);
 | 
			
		||||
 | 
			
		||||
            var services = queryResult.Response.Select(BuildService);
 | 
			
		||||
 | 
			
		||||
            return services.ToList();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Service BuildService(ServiceEntry serviceEntry)
 | 
			
		||||
        {
 | 
			
		||||
            return new Service(
 | 
			
		||||
                serviceEntry.Service.Service,
 | 
			
		||||
                new HostAndPort(serviceEntry.Service.Address, serviceEntry.Service.Port),
 | 
			
		||||
                serviceEntry.Service.ID,
 | 
			
		||||
                GetVersionFromStrings(serviceEntry.Service.Tags),
 | 
			
		||||
                serviceEntry.Service.Tags ?? Enumerable.Empty<string>());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string GetVersionFromStrings(IEnumerable<string> strings)
 | 
			
		||||
        {
 | 
			
		||||
            return strings
 | 
			
		||||
                ?.FirstOrDefault(x => x.StartsWith(VersionPrefix, StringComparison.Ordinal))
 | 
			
		||||
                .TrimStart(VersionPrefix);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
{
 | 
			
		||||
    public interface IServiceDiscoveryProvider
 | 
			
		||||
    {
 | 
			
		||||
         List<Service> Get();
 | 
			
		||||
         Task<List<Service>> Get();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
@@ -9,20 +10,25 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
        {
 | 
			
		||||
            if (serviceConfig.UseServiceDiscovery)
 | 
			
		||||
            {
 | 
			
		||||
                return GetServiceDiscoveryProvider(serviceConfig.ServiceName, serviceConfig.ServiceDiscoveryProvider);
 | 
			
		||||
                return GetServiceDiscoveryProvider(serviceConfig.ServiceName, serviceConfig.ServiceDiscoveryProvider, serviceConfig.ServiceProviderHost, serviceConfig.ServiceProviderPort);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var services = new List<Service>()
 | 
			
		||||
            {
 | 
			
		||||
                new Service(serviceConfig.ServiceName, new HostAndPort(serviceConfig.DownstreamHost, serviceConfig.DownstreamPort))
 | 
			
		||||
                new Service(serviceConfig.ServiceName, 
 | 
			
		||||
                new HostAndPort(serviceConfig.DownstreamHost, serviceConfig.DownstreamPort),
 | 
			
		||||
                string.Empty, 
 | 
			
		||||
                string.Empty, 
 | 
			
		||||
                new string[0])
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            return new ConfigurationServiceProvider(services);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IServiceDiscoveryProvider GetServiceDiscoveryProvider(string serviceName, string serviceProviderName)
 | 
			
		||||
        private IServiceDiscoveryProvider GetServiceDiscoveryProvider(string serviceName, string serviceProviderName, string providerHostName, int providerPort)
 | 
			
		||||
        {
 | 
			
		||||
            return new ConsulServiceDiscoveryProvider();
 | 
			
		||||
            var consulRegistryConfiguration = new ConsulRegistryConfiguration(providerHostName, providerPort, serviceName);
 | 
			
		||||
            return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +1,29 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Values
 | 
			
		||||
{
 | 
			
		||||
    public class Service
 | 
			
		||||
    {
 | 
			
		||||
        public Service(string name, HostAndPort hostAndPort)
 | 
			
		||||
        public Service(string name, 
 | 
			
		||||
            HostAndPort hostAndPort, 
 | 
			
		||||
            string id, 
 | 
			
		||||
            string version, 
 | 
			
		||||
            IEnumerable<string> tags)
 | 
			
		||||
        {
 | 
			
		||||
            Name = name;
 | 
			
		||||
            HostAndPort = hostAndPort;
 | 
			
		||||
            Id = id;
 | 
			
		||||
            Version = version;
 | 
			
		||||
            Tags = tags;
 | 
			
		||||
        }
 | 
			
		||||
        public string Name {get; private set;}
 | 
			
		||||
        public HostAndPort HostAndPort {get; private set;}
 | 
			
		||||
        public string Id { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public string Name { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public string Version { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<string> Tags { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public HostAndPort HostAndPort { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user