mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 15:10:50 +08:00 
			
		
		
		
	Feature/expose http handlers (#224)
* temp commit * trying to work out how to expose the http handlers in a decent way.. * pissing about at lunch * changed to func so you can instanciate object or new it up each time * docs for dele handlers * upgraded to sdk 2.1.4 * some validation for consul services
This commit is contained in:
		@@ -0,0 +1,7 @@
 | 
			
		||||
namespace Ocelot.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    public interface IOcelotAdministrationBuilder
 | 
			
		||||
    {
 | 
			
		||||
        IOcelotAdministrationBuilder AddRafty();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using Butterfly.Client.AspNetCore;
 | 
			
		||||
using CacheManager.Core;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
@@ -10,5 +11,6 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
        IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
 | 
			
		||||
        IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings);      
 | 
			
		||||
        IOcelotAdministrationBuilder AddAdministration(string path, string secret);
 | 
			
		||||
        IOcelotBuilder AddDelegatingHandler(Func<DelegatingHandler> delegatingHandler);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Ocelot.Raft;
 | 
			
		||||
using Rafty.Concensus;
 | 
			
		||||
using Rafty.FiniteStateMachine;
 | 
			
		||||
using Rafty.Infrastructure;
 | 
			
		||||
using Rafty.Log;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    public class OcelotAdministrationBuilder : IOcelotAdministrationBuilder
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceCollection _services;
 | 
			
		||||
        private readonly IConfiguration _configurationRoot;
 | 
			
		||||
        
 | 
			
		||||
        public OcelotAdministrationBuilder(IServiceCollection services, IConfiguration configurationRoot)
 | 
			
		||||
        {
 | 
			
		||||
            _configurationRoot = configurationRoot;
 | 
			
		||||
            _services = services;    
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public IOcelotAdministrationBuilder AddRafty()
 | 
			
		||||
        {
 | 
			
		||||
            var settings = new InMemorySettings(4000, 5000, 100, 5000);
 | 
			
		||||
            _services.AddSingleton<ILog, SqlLiteLog>();
 | 
			
		||||
            _services.AddSingleton<IFiniteStateMachine, OcelotFiniteStateMachine>();
 | 
			
		||||
            _services.AddSingleton<ISettings>(settings);
 | 
			
		||||
            _services.AddSingleton<IPeersProvider, FilePeersProvider>();
 | 
			
		||||
            _services.AddSingleton<INode, Node>();
 | 
			
		||||
            _services.Configure<FilePeers>(_configurationRoot);
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +1,12 @@
 | 
			
		||||
using Butterfly.Client.AspNetCore;
 | 
			
		||||
using CacheManager.Core;
 | 
			
		||||
using IdentityServer4.AccessTokenValidation;
 | 
			
		||||
using IdentityServer4.Models;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection.Extensions;
 | 
			
		||||
using Ocelot.Authorisation;
 | 
			
		||||
using Ocelot.Cache;
 | 
			
		||||
using Ocelot.Claims;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Authentication;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Configuration.Parser;
 | 
			
		||||
@@ -32,7 +25,6 @@ using Ocelot.LoadBalancer.LoadBalancers;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using Ocelot.QueryStrings;
 | 
			
		||||
using Ocelot.Raft;
 | 
			
		||||
using Ocelot.RateLimit;
 | 
			
		||||
using Ocelot.Request.Builder;
 | 
			
		||||
using Ocelot.Request.Mapper;
 | 
			
		||||
@@ -40,24 +32,29 @@ using Ocelot.Requester;
 | 
			
		||||
using Ocelot.Requester.QoS;
 | 
			
		||||
using Ocelot.Responder;
 | 
			
		||||
using Ocelot.ServiceDiscovery;
 | 
			
		||||
using Rafty.Concensus;
 | 
			
		||||
using Rafty.FiniteStateMachine;
 | 
			
		||||
using Rafty.Infrastructure;
 | 
			
		||||
using Rafty.Log;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IdentityModel.Tokens.Jwt;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Security.Cryptography.X509Certificates;
 | 
			
		||||
using IdentityServer4.AccessTokenValidation;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection.Extensions;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Butterfly.Client.AspNetCore;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    public class OcelotBuilder : IOcelotBuilder
 | 
			
		||||
    {
 | 
			
		||||
        private IServiceCollection _services;
 | 
			
		||||
        private IConfiguration _configurationRoot;
 | 
			
		||||
        private readonly IServiceCollection _services;
 | 
			
		||||
        private readonly IConfiguration _configurationRoot;
 | 
			
		||||
        private IDelegatingHandlerHandlerProvider _provider;
 | 
			
		||||
        
 | 
			
		||||
        public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
 | 
			
		||||
        {
 | 
			
		||||
@@ -122,6 +119,9 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            _services.TryAddSingleton<IRequestMapper, RequestMapper>();
 | 
			
		||||
            _services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>();
 | 
			
		||||
            _services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>();
 | 
			
		||||
            _services.TryAddSingleton<IDelegatingHandlerHandlerProviderFactory, DelegatingHandlerHandlerProviderFactory>();
 | 
			
		||||
            _services.TryAddSingleton<IDelegatingHandlerHandlerHouse, DelegatingHandlerHandlerHouse>();
 | 
			
		||||
 | 
			
		||||
            // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
 | 
			
		||||
            // could maybe use a scoped data repository
 | 
			
		||||
            _services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 | 
			
		||||
@@ -142,6 +142,11 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            _services.AddMiddlewareAnalysis();
 | 
			
		||||
            _services.AddWebEncoders();
 | 
			
		||||
            _services.AddSingleton<IAdministrationPath>(new NullAdministrationPath());
 | 
			
		||||
 | 
			
		||||
            //these get picked out later and added to http request
 | 
			
		||||
            _provider = new DelegatingHandlerHandlerProvider();
 | 
			
		||||
            _services.TryAddSingleton<IDelegatingHandlerHandlerProvider>(_provider);
 | 
			
		||||
            _services.AddTransient<ITracingHandler, NoTracingHandler>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
 | 
			
		||||
@@ -161,6 +166,19 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            return new OcelotAdministrationBuilder(_services, _configurationRoot);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotBuilder AddDelegatingHandler(Func<DelegatingHandler> delegatingHandler)
 | 
			
		||||
        {
 | 
			
		||||
            _provider.Add(delegatingHandler);
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings)
 | 
			
		||||
        {
 | 
			
		||||
            _services.AddTransient<ITracingHandler, OcelotHttpTracingHandler>();
 | 
			
		||||
            _services.AddButterfly(settings);   
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotBuilder AddStoreOcelotConfigurationInConsul()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0);
 | 
			
		||||
@@ -203,13 +221,6 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings)
 | 
			
		||||
        {
 | 
			
		||||
            _services.AddTransient<OcelotHttpTracingHandler>();
 | 
			
		||||
            _services.AddButterfly(settings);   
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath) 
 | 
			
		||||
        {
 | 
			
		||||
            _services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
 | 
			
		||||
@@ -281,33 +292,4 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public interface IOcelotAdministrationBuilder
 | 
			
		||||
    {
 | 
			
		||||
        IOcelotAdministrationBuilder AddRafty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class OcelotAdministrationBuilder : IOcelotAdministrationBuilder
 | 
			
		||||
    {
 | 
			
		||||
        private IServiceCollection _services;
 | 
			
		||||
        private IConfiguration _configurationRoot;
 | 
			
		||||
        
 | 
			
		||||
        public OcelotAdministrationBuilder(IServiceCollection services, IConfiguration configurationRoot)
 | 
			
		||||
        {
 | 
			
		||||
            _configurationRoot = configurationRoot;
 | 
			
		||||
            _services = services;    
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public IOcelotAdministrationBuilder AddRafty()
 | 
			
		||||
        {
 | 
			
		||||
            var settings = new InMemorySettings(4000, 5000, 100, 5000);
 | 
			
		||||
            _services.AddSingleton<ILog, SqlLiteLog>();
 | 
			
		||||
            _services.AddSingleton<IFiniteStateMachine, OcelotFiniteStateMachine>();
 | 
			
		||||
            _services.AddSingleton<ISettings>(settings);
 | 
			
		||||
            _services.AddSingleton<IPeersProvider, FilePeersProvider>();
 | 
			
		||||
            _services.AddSingleton<INode, Node>();
 | 
			
		||||
            _services.Configure<FilePeers>(_configurationRoot);
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ namespace Ocelot.Errors.Middleware
 | 
			
		||||
        private async Task TrySetGlobalRequestId(HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
                //try and get the global request id and set it for logs...
 | 
			
		||||
                //shoudl this basically be immutable per request...i guess it should!
 | 
			
		||||
                //should this basically be immutable per request...i guess it should!
 | 
			
		||||
                //first thing is get config
 | 
			
		||||
                 var configuration = await _configProvider.Get(); 
 | 
			
		||||
            
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
        UnmappableRequestError,
 | 
			
		||||
        RateLimitOptionsError,
 | 
			
		||||
        PathTemplateDoesntStartWithForwardSlash,
 | 
			
		||||
        FileValidationFailedError
 | 
			
		||||
        FileValidationFailedError,
 | 
			
		||||
        UnableToFindDelegatingHandlerProviderError
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,4 +9,4 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.LoadBalancer.LoadBalancers;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
@@ -46,11 +45,14 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var uriBuilder = new UriBuilder(DownstreamRequest.RequestUri);
 | 
			
		||||
 | 
			
		||||
            uriBuilder.Host = hostAndPort.Data.DownstreamHost;
 | 
			
		||||
 | 
			
		||||
            if (hostAndPort.Data.DownstreamPort > 0)
 | 
			
		||||
            {
 | 
			
		||||
                uriBuilder.Port = hostAndPort.Data.DownstreamPort;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            DownstreamRequest.RequestUri = uriBuilder.Uri;
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,10 @@ namespace Ocelot.Request.Builder
 | 
			
		||||
            IQoSProvider qosProvider,
 | 
			
		||||
            bool useCookieContainer,
 | 
			
		||||
            bool allowAutoRedirect,
 | 
			
		||||
            string reRouteKey,
 | 
			
		||||
            bool isTracing)
 | 
			
		||||
        {
 | 
			
		||||
            return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider, allowAutoRedirect, useCookieContainer, isTracing));
 | 
			
		||||
             return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider, allowAutoRedirect, useCookieContainer, reRouteKey, isTracing));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            IQoSProvider qosProvider,
 | 
			
		||||
            bool useCookieContainer,
 | 
			
		||||
            bool allowAutoRedirect,
 | 
			
		||||
            string reRouteKe,
 | 
			
		||||
            bool isTracing);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,9 @@ namespace Ocelot.Request.Middleware
 | 
			
		||||
                    qosProvider.Data,
 | 
			
		||||
                    DownstreamRoute.ReRoute.HttpHandlerOptions.UseCookieContainer,
 | 
			
		||||
                    DownstreamRoute.ReRoute.HttpHandlerOptions.AllowAutoRedirect,
 | 
			
		||||
                    DownstreamRoute.ReRoute.ReRouteKey,
 | 
			
		||||
                    DownstreamRoute.ReRoute.HttpHandlerOptions.UseTracing);
 | 
			
		||||
                    
 | 
			
		||||
            if (buildResult.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("IRequestCreator returned an error, setting pipeline error");
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ namespace Ocelot.Request
 | 
			
		||||
            IQoSProvider qosProvider, 
 | 
			
		||||
            bool allowAutoRedirect,
 | 
			
		||||
            bool useCookieContainer,
 | 
			
		||||
            string reRouteKey,
 | 
			
		||||
            bool isTracing
 | 
			
		||||
            )
 | 
			
		||||
        {
 | 
			
		||||
@@ -19,6 +20,7 @@ namespace Ocelot.Request
 | 
			
		||||
            QosProvider = qosProvider;
 | 
			
		||||
            AllowAutoRedirect = allowAutoRedirect;
 | 
			
		||||
            UseCookieContainer = useCookieContainer;
 | 
			
		||||
            ReRouteKey = reRouteKey;
 | 
			
		||||
            IsTracing = isTracing;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -28,5 +30,6 @@ namespace Ocelot.Request
 | 
			
		||||
        public IQoSProvider QosProvider { get; private set; }
 | 
			
		||||
        public bool AllowAutoRedirect { get; private set; }
 | 
			
		||||
        public bool UseCookieContainer { get; private set; }
 | 
			
		||||
        public string ReRouteKey { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								src/Ocelot/Requester/DelegatingHandlerHandlerHouse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/Ocelot/Requester/DelegatingHandlerHandlerHouse.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class DelegatingHandlerHandlerHouse : IDelegatingHandlerHandlerHouse
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IDelegatingHandlerHandlerProviderFactory _factory;
 | 
			
		||||
        private readonly ConcurrentDictionary<string, IDelegatingHandlerHandlerProvider> _housed;
 | 
			
		||||
 | 
			
		||||
        public DelegatingHandlerHandlerHouse(IDelegatingHandlerHandlerProviderFactory factory)
 | 
			
		||||
        {
 | 
			
		||||
            _factory = factory;
 | 
			
		||||
            _housed = new ConcurrentDictionary<string, IDelegatingHandlerHandlerProvider>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<IDelegatingHandlerHandlerProvider> Get(Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (_housed.TryGetValue(request.ReRouteKey, out var provider))
 | 
			
		||||
                {
 | 
			
		||||
                    //todo once day we might need a check here to see if we need to create a new provider
 | 
			
		||||
                    provider = _housed[request.ReRouteKey];
 | 
			
		||||
                    return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                provider = _factory.Get(request);
 | 
			
		||||
                AddHoused(request.ReRouteKey, provider);
 | 
			
		||||
                return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<IDelegatingHandlerHandlerProvider>(new List<Error>()
 | 
			
		||||
                {
 | 
			
		||||
                    new UnableToFindDelegatingHandlerProviderError($"unabe to find delegating handler provider for {request.ReRouteKey} exception is {ex}")
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddHoused(string key, IDelegatingHandlerHandlerProvider provider)
 | 
			
		||||
        {
 | 
			
		||||
            _housed.AddOrUpdate(key, provider, (k, v) => provider);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/Ocelot/Requester/DelegatingHandlerHandlerProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Ocelot/Requester/DelegatingHandlerHandlerProvider.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class DelegatingHandlerHandlerProvider : IDelegatingHandlerHandlerProvider
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Dictionary<int, Func<DelegatingHandler>> _handlers;
 | 
			
		||||
 | 
			
		||||
        public DelegatingHandlerHandlerProvider()
 | 
			
		||||
        {
 | 
			
		||||
            _handlers = new Dictionary<int, Func<DelegatingHandler>>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Add(Func<DelegatingHandler> handler)
 | 
			
		||||
        {
 | 
			
		||||
            var key = _handlers.Count == 0 ? 0 : _handlers.Count + 1;
 | 
			
		||||
            _handlers[key] = handler;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<Func<DelegatingHandler>> Get()
 | 
			
		||||
        {
 | 
			
		||||
            return _handlers.Count > 0 ? _handlers.OrderBy(x => x.Key).Select(x => x.Value).ToList() : new List<Func<DelegatingHandler>>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,43 @@
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class DelegatingHandlerHandlerProviderFactory : IDelegatingHandlerHandlerProviderFactory
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ITracingHandler _tracingHandler;
 | 
			
		||||
        private readonly IOcelotLoggerFactory _loggerFactory;
 | 
			
		||||
        private readonly IDelegatingHandlerHandlerProvider _allRoutesProvider;
 | 
			
		||||
 | 
			
		||||
        public DelegatingHandlerHandlerProviderFactory(IOcelotLoggerFactory loggerFactory, IDelegatingHandlerHandlerProvider allRoutesProvider, ITracingHandler tracingHandler)
 | 
			
		||||
        {
 | 
			
		||||
            _tracingHandler = tracingHandler;
 | 
			
		||||
            _loggerFactory = loggerFactory;
 | 
			
		||||
            _allRoutesProvider = allRoutesProvider;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IDelegatingHandlerHandlerProvider Get(Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            var handlersAppliedToAll = _allRoutesProvider.Get();
 | 
			
		||||
 | 
			
		||||
            var provider = new DelegatingHandlerHandlerProvider();
 | 
			
		||||
 | 
			
		||||
            foreach (var handler in handlersAppliedToAll)
 | 
			
		||||
            {
 | 
			
		||||
                provider.Add(handler);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (request.IsTracing)
 | 
			
		||||
            {
 | 
			
		||||
                provider.Add(() => (DelegatingHandler)_tracingHandler);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (request.IsQos)
 | 
			
		||||
            {
 | 
			
		||||
                provider.Add(() => new PollyCircuitBreakingDelegatingHandler(request.QosProvider, _loggerFactory));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return provider;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,48 +1,33 @@
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Requester.QoS;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    internal class HttpClientBuilder : IHttpClientBuilder
 | 
			
		||||
    public class HttpClientBuilder : IHttpClientBuilder
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Dictionary<int, Func<DelegatingHandler>> _handlers = new Dictionary<int, Func<DelegatingHandler>>();
 | 
			
		||||
        private readonly IDelegatingHandlerHandlerHouse _house;
 | 
			
		||||
 | 
			
		||||
        public  IHttpClientBuilder WithQos(IQoSProvider qosProvider, IOcelotLogger logger)
 | 
			
		||||
        public HttpClientBuilder(IDelegatingHandlerHandlerHouse house)
 | 
			
		||||
        {
 | 
			
		||||
            _handlers.Add(5000, () => new PollyCircuitBreakingDelegatingHandler(qosProvider, logger));
 | 
			
		||||
 | 
			
		||||
            return this;
 | 
			
		||||
            _house = house;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IHttpClientBuilder WithTracing(IServiceProvider provider)
 | 
			
		||||
        public IHttpClient Create(Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            _handlers.Add(6000, () => provider.GetService<OcelotHttpTracingHandler>());
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IHttpClient Create(bool useCookies, bool allowAutoRedirect, bool isTracing, IServiceProvider provider)
 | 
			
		||||
        {
 | 
			
		||||
            var httpclientHandler = new HttpClientHandler { AllowAutoRedirect = allowAutoRedirect, UseCookies = useCookies };
 | 
			
		||||
            if (isTracing)
 | 
			
		||||
            {
 | 
			
		||||
                WithTracing(provider);
 | 
			
		||||
            }
 | 
			
		||||
            var client = new HttpClient(CreateHttpMessageHandler(httpclientHandler));                
 | 
			
		||||
            var httpclientHandler = new HttpClientHandler { AllowAutoRedirect = request.AllowAutoRedirect, UseCookies = request.UseCookieContainer};
 | 
			
		||||
            
 | 
			
		||||
            var client = new HttpClient(CreateHttpMessageHandler(httpclientHandler, request));                
 | 
			
		||||
            
 | 
			
		||||
            return new HttpClientWrapper(client);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private HttpMessageHandler CreateHttpMessageHandler(HttpMessageHandler httpMessageHandler)
 | 
			
		||||
        {            
 | 
			
		||||
            _handlers
 | 
			
		||||
                .OrderByDescending(handler => handler.Key)
 | 
			
		||||
                .Select(handler => handler.Value)
 | 
			
		||||
        private HttpMessageHandler CreateHttpMessageHandler(HttpMessageHandler httpMessageHandler, Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            var provider = _house.Get(request);
 | 
			
		||||
 | 
			
		||||
            //todo handle error
 | 
			
		||||
            provider.Data.Get()
 | 
			
		||||
                .Select(handler => handler)
 | 
			
		||||
                .Reverse()
 | 
			
		||||
                .ToList()
 | 
			
		||||
                .ForEach(handler =>
 | 
			
		||||
@@ -54,22 +39,4 @@ namespace Ocelot.Requester
 | 
			
		||||
            return httpMessageHandler;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This class was made to make unit testing easier when HttpClient is used.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class HttpClientWrapper : IHttpClient
 | 
			
		||||
    {
 | 
			
		||||
        public HttpClient Client { get; }
 | 
			
		||||
 | 
			
		||||
        public HttpClientWrapper(HttpClient client)
 | 
			
		||||
        {
 | 
			
		||||
            Client = client;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
 | 
			
		||||
        {
 | 
			
		||||
            return Client.SendAsync(request);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,84 +1,84 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Polly.CircuitBreaker;
 | 
			
		||||
using Polly.Timeout;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class HttpClientHttpRequester : IHttpRequester
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IHttpClientCache _cacheHandlers;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IServiceProvider _serviceProvider;
 | 
			
		||||
 | 
			
		||||
        public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory, IHttpClientCache cacheHandlers, IServiceProvider provider)
 | 
			
		||||
        {
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
 | 
			
		||||
            _cacheHandlers = cacheHandlers;
 | 
			
		||||
            _serviceProvider = provider;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            var builder = new HttpClientBuilder();
 | 
			
		||||
 | 
			
		||||
            var cacheKey = GetCacheKey(request, builder);
 | 
			
		||||
            
 | 
			
		||||
            var httpClient = GetHttpClient(cacheKey, builder, request.UseCookieContainer, request.AllowAutoRedirect, request.IsTracing);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var response = await httpClient.SendAsync(request.HttpRequestMessage);
 | 
			
		||||
                return new OkResponse<HttpResponseMessage>(response);
 | 
			
		||||
            }
 | 
			
		||||
            catch (TimeoutRejectedException exception)
 | 
			
		||||
            {
 | 
			
		||||
                return
 | 
			
		||||
                    new ErrorResponse<HttpResponseMessage>(new RequestTimedOutError(exception));
 | 
			
		||||
            }
 | 
			
		||||
            catch (BrokenCircuitException exception)
 | 
			
		||||
            {
 | 
			
		||||
                return
 | 
			
		||||
                    new ErrorResponse<HttpResponseMessage>(new RequestTimedOutError(exception));
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception exception)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<HttpResponseMessage>(new UnableToCompleteRequestError(exception));
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                _cacheHandlers.Set(cacheKey, httpClient, TimeSpan.FromHours(24));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, bool useCookieContainer, bool allowAutoRedirect,bool isTracing)
 | 
			
		||||
        {
 | 
			
		||||
            var httpClient = _cacheHandlers.Get(cacheKey);
 | 
			
		||||
 | 
			
		||||
            if (httpClient == null)
 | 
			
		||||
            {
 | 
			
		||||
                httpClient = builder.Create(useCookieContainer, allowAutoRedirect, isTracing, _serviceProvider);
 | 
			
		||||
            }
 | 
			
		||||
            return httpClient;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string GetCacheKey(Request.Request request, IHttpClientBuilder builder)
 | 
			
		||||
        {
 | 
			
		||||
            string baseUrl = $"{request.HttpRequestMessage.RequestUri.Scheme}://{request.HttpRequestMessage.RequestUri.Authority}";
 | 
			
		||||
 | 
			
		||||
            if (request.IsQos)
 | 
			
		||||
            {
 | 
			
		||||
                builder.WithQos(request.QosProvider, _logger);
 | 
			
		||||
                baseUrl = $"{baseUrl}{request.QosProvider.CircuitBreaker.CircuitBreakerPolicy.PolicyKey}";
 | 
			
		||||
            }
 | 
			
		||||
           
 | 
			
		||||
            return baseUrl;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
using System;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Polly.CircuitBreaker;
 | 
			
		||||
using Polly.Timeout;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class HttpClientHttpRequester : IHttpRequester
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IHttpClientCache _cacheHandlers;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IDelegatingHandlerHandlerHouse _house;
 | 
			
		||||
 | 
			
		||||
        public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory, 
 | 
			
		||||
            IHttpClientCache cacheHandlers,
 | 
			
		||||
            IDelegatingHandlerHandlerHouse house)
 | 
			
		||||
        {
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
 | 
			
		||||
            _cacheHandlers = cacheHandlers;
 | 
			
		||||
            _house = house;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            var builder = new HttpClientBuilder(_house);
 | 
			
		||||
 | 
			
		||||
            var cacheKey = GetCacheKey(request);
 | 
			
		||||
            
 | 
			
		||||
            var httpClient = GetHttpClient(cacheKey, builder, request);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var response = await httpClient.SendAsync(request.HttpRequestMessage);
 | 
			
		||||
                return new OkResponse<HttpResponseMessage>(response);
 | 
			
		||||
            }
 | 
			
		||||
            catch (TimeoutRejectedException exception)
 | 
			
		||||
            {
 | 
			
		||||
                return
 | 
			
		||||
                    new ErrorResponse<HttpResponseMessage>(new RequestTimedOutError(exception));
 | 
			
		||||
            }
 | 
			
		||||
            catch (BrokenCircuitException exception)
 | 
			
		||||
            {
 | 
			
		||||
                return
 | 
			
		||||
                    new ErrorResponse<HttpResponseMessage>(new RequestTimedOutError(exception));
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception exception)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<HttpResponseMessage>(new UnableToCompleteRequestError(exception));
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                _cacheHandlers.Set(cacheKey, httpClient, TimeSpan.FromHours(24));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            var httpClient = _cacheHandlers.Get(cacheKey);
 | 
			
		||||
 | 
			
		||||
            if (httpClient == null)
 | 
			
		||||
            {
 | 
			
		||||
                httpClient = builder.Create(request);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return httpClient;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string GetCacheKey(Request.Request request)
 | 
			
		||||
        {
 | 
			
		||||
            var baseUrl = $"{request.HttpRequestMessage.RequestUri.Scheme}://{request.HttpRequestMessage.RequestUri.Authority}";
 | 
			
		||||
 | 
			
		||||
            if (request.IsQos)
 | 
			
		||||
            {
 | 
			
		||||
                baseUrl = $"{baseUrl}{request.QosProvider.CircuitBreaker.CircuitBreakerPolicy.PolicyKey}";
 | 
			
		||||
            }
 | 
			
		||||
           
 | 
			
		||||
            return baseUrl;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/Ocelot/Requester/HttpClientWrapper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Ocelot/Requester/HttpClientWrapper.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This class was made to make unit testing easier when HttpClient is used.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class HttpClientWrapper : IHttpClient
 | 
			
		||||
    {
 | 
			
		||||
        public HttpClient Client { get; }
 | 
			
		||||
 | 
			
		||||
        public HttpClientWrapper(HttpClient client)
 | 
			
		||||
        {
 | 
			
		||||
            Client = client;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
 | 
			
		||||
        {
 | 
			
		||||
            return Client.SendAsync(request);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								src/Ocelot/Requester/IDelegatingHandlerHandlerHouse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Ocelot/Requester/IDelegatingHandlerHandlerHouse.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public interface IDelegatingHandlerHandlerHouse
 | 
			
		||||
    {
 | 
			
		||||
        Response<IDelegatingHandlerHandlerProvider> Get(Request.Request request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/Ocelot/Requester/IDelegatingHandlerHandlerProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Ocelot/Requester/IDelegatingHandlerHandlerProvider.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public interface IDelegatingHandlerHandlerProvider
 | 
			
		||||
    {
 | 
			
		||||
        void Add(Func<DelegatingHandler> handler);
 | 
			
		||||
        List<Func<DelegatingHandler>> Get();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public interface IDelegatingHandlerHandlerProviderFactory
 | 
			
		||||
    {
 | 
			
		||||
        IDelegatingHandlerHandlerProvider Get(Request.Request request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,27 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Requester.QoS;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public interface IHttpClientBuilder
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets a PollyCircuitBreakingDelegatingHandler .
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IHttpClientBuilder WithQos(IQoSProvider qosProvider, IOcelotLogger logger);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates the <see cref="HttpClient"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="useCookies">Defines if http client should use cookie container</param>
 | 
			
		||||
        /// <param name="allowAutoRedirect">Defines if http client should allow auto redirect</param>
 | 
			
		||||
        IHttpClient Create(bool useCookies, bool allowAutoRedirect, bool isTracing, IServiceProvider provider);
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="request"></param>
 | 
			
		||||
        IHttpClient Create(Request.Request request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,16 @@ using Butterfly.OpenTracing;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class OcelotHttpTracingHandler : DelegatingHandler
 | 
			
		||||
    public interface ITracingHandler
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class NoTracingHandler : DelegatingHandler, ITracingHandler
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceTracer _tracer;
 | 
			
		||||
        private const string prefix_spanId = "ot-spanId";
 | 
			
		||||
 
 | 
			
		||||
@@ -16,10 +16,10 @@ namespace Ocelot.Requester
 | 
			
		||||
 | 
			
		||||
        public PollyCircuitBreakingDelegatingHandler(
 | 
			
		||||
            IQoSProvider qoSProvider,
 | 
			
		||||
            IOcelotLogger logger)
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory)
 | 
			
		||||
        {
 | 
			
		||||
            _qoSProvider = qoSProvider;
 | 
			
		||||
            _logger = logger;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<PollyCircuitBreakingDelegatingHandler>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class UnableToFindDelegatingHandlerProviderError : Error
 | 
			
		||||
    {
 | 
			
		||||
        public UnableToFindDelegatingHandlerProviderError(string message)
 | 
			
		||||
            : base(message, OcelotErrorCode.UnableToFindDelegatingHandlerProviderError)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,7 @@ using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Ocelot.Infrastructure.Extensions;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
@@ -11,13 +12,18 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
    public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConsulRegistryConfiguration _consulConfig;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly ConsulClient _consul;
 | 
			
		||||
        private const string VersionPrefix = "version-";
 | 
			
		||||
 | 
			
		||||
        public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration consulRegistryConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
        public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration consulRegistryConfiguration, IOcelotLoggerFactory factory)
 | 
			
		||||
        {;
 | 
			
		||||
            _logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
 | 
			
		||||
 | 
			
		||||
            var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName;
 | 
			
		||||
 | 
			
		||||
            var consulPort = consulRegistryConfiguration?.Port ?? 8500;
 | 
			
		||||
 | 
			
		||||
            _consulConfig = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.KeyOfServiceInConsul);
 | 
			
		||||
 | 
			
		||||
            _consul = new ConsulClient(config =>
 | 
			
		||||
@@ -30,7 +36,19 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
        {
 | 
			
		||||
            var queryResult = await _consul.Health.Service(_consulConfig.KeyOfServiceInConsul, string.Empty, true);
 | 
			
		||||
 | 
			
		||||
            var services = queryResult.Response.Select(BuildService);
 | 
			
		||||
            var services = new List<Service>();
 | 
			
		||||
 | 
			
		||||
            foreach (var serviceEntry in queryResult.Response)
 | 
			
		||||
            {
 | 
			
		||||
                if (IsValid(serviceEntry))
 | 
			
		||||
                {
 | 
			
		||||
                    services.Add(BuildService(serviceEntry));
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogError($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return services.ToList();
 | 
			
		||||
        }
 | 
			
		||||
@@ -45,6 +63,16 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
                serviceEntry.Service.Tags ?? Enumerable.Empty<string>());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool IsValid(ServiceEntry serviceEntry)
 | 
			
		||||
        {
 | 
			
		||||
            if (serviceEntry.Service.Address.Contains("http://") || serviceEntry.Service.Address.Contains("https://") || serviceEntry.Service.Port <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string GetVersionFromStrings(IEnumerable<string> strings)
 | 
			
		||||
        {
 | 
			
		||||
            return strings
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,19 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.ServiceDiscovery
 | 
			
		||||
{
 | 
			
		||||
    public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IOcelotLoggerFactory _factory;
 | 
			
		||||
 | 
			
		||||
        public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory)
 | 
			
		||||
        {
 | 
			
		||||
            _factory = factory;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public  IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, ReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            if (reRoute.UseServiceDiscovery)
 | 
			
		||||
@@ -28,7 +36,7 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
        private IServiceDiscoveryProvider GetServiceDiscoveryProvider(string keyOfServiceInConsul, string providerHostName, int providerPort)
 | 
			
		||||
        {
 | 
			
		||||
            var consulRegistryConfiguration = new ConsulRegistryConfiguration(providerHostName, providerPort, keyOfServiceInConsul);
 | 
			
		||||
            return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration);
 | 
			
		||||
            return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user