mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 17:10:50 +08:00 
			
		
		
		
	Feature/#246 (#252)
* failing test * failing test but needs real butterfly server running..need to fix that...also worked out ive broken tracing...yey * brought in butterfly source code so i can work out how to write acceptance tests for this... * fixed the bug but still need to fix tracing * tracing working again across services but need to make tracing hook into new Ocelot middleware as it still uses asp.net middleware * removed butterfly libs brought in for testing
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								docs/favicon.ico
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/favicon.ico
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 8.1 KiB  | 
@@ -21,7 +21,7 @@ All you need to do to hook into your own IdentityServer is add the following to
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        services
 | 
					        services
 | 
				
			||||||
            .AddOcelot(Configuration)
 | 
					            .AddOcelot()
 | 
				
			||||||
            .AddAdministration("/administration", options);
 | 
					            .AddAdministration("/administration", options);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,7 +51,7 @@ The secret is the client secret that Ocelot's internal IdentityServer will use t
 | 
				
			|||||||
    public virtual void ConfigureServices(IServiceCollection services)
 | 
					    public virtual void ConfigureServices(IServiceCollection services)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        services
 | 
					        services
 | 
				
			||||||
            .AddOcelot(Configuration)
 | 
					            .AddOcelot()
 | 
				
			||||||
            .AddAdministration("/administration", "secret");
 | 
					            .AddAdministration("/administration", "secret");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,7 +63,7 @@ If you want to authenticate using JWT tokens maybe from a provider like Auth0 yo
 | 
				
			|||||||
                x.Audience = "test";
 | 
					                x.Audience = "test";
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        services.AddOcelot(Configuration);
 | 
					        services.AddOcelot();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Then map the authentication provider key to a ReRoute in your configuration e.g.
 | 
					Then map the authentication provider key to a ReRoute in your configuration e.g.
 | 
				
			||||||
@@ -111,7 +111,7 @@ In order to use IdentityServer bearer tokens register your IdentityServer servic
 | 
				
			|||||||
        services.AddAuthentication()
 | 
					        services.AddAuthentication()
 | 
				
			||||||
            .AddIdentityServerAuthentication(authenticationProviderKey, options);
 | 
					            .AddIdentityServerAuthentication(authenticationProviderKey, options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        services.AddOcelot(Configuration);
 | 
					        services.AddOcelot();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Then map the authentication provider key to a ReRoute in your configuration e.g.
 | 
					Then map the authentication provider key to a ReRoute in your configuration e.g.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,7 +109,7 @@ If you add the following when you register your services Ocelot will attempt to
 | 
				
			|||||||
.. code-block:: csharp
 | 
					.. code-block:: csharp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 services
 | 
					 services
 | 
				
			||||||
    .AddOcelot(Configuration)
 | 
					    .AddOcelot()
 | 
				
			||||||
    .AddStoreOcelotConfigurationInConsul();
 | 
					    .AddStoreOcelotConfigurationInConsul();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You also need to add the following to your configuration.json. This is how Ocelot
 | 
					You also need to add the following to your configuration.json. This is how Ocelot
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ In order to enable Rafty in Ocelot you must make the following changes to your S
 | 
				
			|||||||
    public virtual void ConfigureServices(IServiceCollection services)
 | 
					    public virtual void ConfigureServices(IServiceCollection services)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
         services
 | 
					         services
 | 
				
			||||||
            .AddOcelot(Configuration)
 | 
					            .AddOcelot()
 | 
				
			||||||
            .AddAdministration("/administration", "secret")
 | 
					            .AddAdministration("/administration", "secret")
 | 
				
			||||||
            .AddRafty();
 | 
					            .AddRafty();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ In your ConfigureServices method
 | 
				
			|||||||
.. code-block:: csharp
 | 
					.. code-block:: csharp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    services
 | 
					    services
 | 
				
			||||||
        .AddOcelot(Configuration)
 | 
					        .AddOcelot()
 | 
				
			||||||
        .AddOpenTracing(option =>
 | 
					        .AddOpenTracing(option =>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            //this is the url that the butterfly collector server is running on...
 | 
					            //this is the url that the butterfly collector server is running on...
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,11 +11,11 @@ namespace Ocelot.Configuration.Repository
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class ConsulFileConfigurationPoller : IDisposable
 | 
					    public class ConsulFileConfigurationPoller : IDisposable
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private IOcelotLogger _logger; 
 | 
					        private readonly IOcelotLogger _logger; 
 | 
				
			||||||
        private IFileConfigurationRepository _repo;
 | 
					        private readonly IFileConfigurationRepository _repo;
 | 
				
			||||||
        private IFileConfigurationSetter _setter;
 | 
					        private readonly IFileConfigurationSetter _setter;
 | 
				
			||||||
        private string _previousAsJson;
 | 
					        private string _previousAsJson;
 | 
				
			||||||
        private Timer _timer;
 | 
					        private readonly Timer _timer;
 | 
				
			||||||
        private bool _polling;
 | 
					        private bool _polling;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ConsulFileConfigurationPoller(IOcelotLoggerFactory factory, IFileConfigurationRepository repo, IFileConfigurationSetter setter)
 | 
					        public ConsulFileConfigurationPoller(IOcelotLoggerFactory factory, IFileConfigurationRepository repo, IFileConfigurationSetter setter)
 | 
				
			||||||
@@ -77,4 +77,4 @@ namespace Ocelot.Configuration.Repository
 | 
				
			|||||||
            _timer.Dispose();
 | 
					            _timer.Dispose();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					using Butterfly.Client.Tracing;
 | 
				
			||||||
using Microsoft.Extensions.Options;
 | 
					using Microsoft.Extensions.Options;
 | 
				
			||||||
using Ocelot.Middleware.Multiplexer;
 | 
					using Ocelot.Middleware.Multiplexer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,10 +147,14 @@ namespace Ocelot.DependencyInjection
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            //these get picked out later and added to http request
 | 
					            //these get picked out later and added to http request
 | 
				
			||||||
            _provider = new DelegatingHandlerHandlerProvider();
 | 
					            _provider = new DelegatingHandlerHandlerProvider();
 | 
				
			||||||
            _services.TryAddSingleton<IDelegatingHandlerHandlerProvider>(_provider);
 | 
					            _services.TryAddSingleton<IDelegatingHandlerHandlerProvider>(_provider);            
 | 
				
			||||||
            _services.AddTransient<ITracingHandler, NoTracingHandler>();
 | 
					 | 
				
			||||||
            _services.TryAddSingleton<IMultiplexer, Multiplexer>();
 | 
					            _services.TryAddSingleton<IMultiplexer, Multiplexer>();
 | 
				
			||||||
            _services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>();
 | 
					            _services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>();
 | 
				
			||||||
 | 
					            _services.AddSingleton<ITracingHandlerFactory, TracingHandlerFactory>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // We add this here so that we can always inject something into the factory for IoC..
 | 
				
			||||||
 | 
					            _services.AddSingleton<IServiceTracer, FakeServiceTracer>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
 | 
					        public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
 | 
				
			||||||
@@ -192,7 +197,8 @@ namespace Ocelot.DependencyInjection
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings)
 | 
					        public IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _services.AddTransient<ITracingHandler, OcelotHttpTracingHandler>();
 | 
					            // Earlier we add FakeServiceTracer and need to remove it here before we add butterfly
 | 
				
			||||||
 | 
					            _services.RemoveAll<IServiceTracer>();
 | 
				
			||||||
            _services.AddButterfly(settings);   
 | 
					            _services.AddButterfly(settings);   
 | 
				
			||||||
            return this;
 | 
					            return this;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,23 +173,34 @@
 | 
				
			|||||||
            var ocelotConfigurationRepository =
 | 
					            var ocelotConfigurationRepository =
 | 
				
			||||||
                (IOcelotConfigurationRepository) builder.ApplicationServices.GetService(
 | 
					                (IOcelotConfigurationRepository) builder.ApplicationServices.GetService(
 | 
				
			||||||
                    typeof(IOcelotConfigurationRepository));
 | 
					                    typeof(IOcelotConfigurationRepository));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var ocelotConfigurationCreator =
 | 
					            var ocelotConfigurationCreator =
 | 
				
			||||||
                (IOcelotConfigurationCreator) builder.ApplicationServices.GetService(
 | 
					                (IOcelotConfigurationCreator) builder.ApplicationServices.GetService(
 | 
				
			||||||
                    typeof(IOcelotConfigurationCreator));
 | 
					                    typeof(IOcelotConfigurationCreator));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var fileConfigFromConsul = await consulFileConfigRepo.Get();
 | 
					            var fileConfigFromConsul = await consulFileConfigRepo.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (fileConfigFromConsul.Data == null)
 | 
					            if (fileConfigFromConsul.Data == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                config = await setter.Set(fileConfig.Value);
 | 
					                config = await setter.Set(fileConfig.Value);
 | 
				
			||||||
 | 
					                var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var ocelotConfig = await ocelotConfigurationCreator.Create(fileConfigFromConsul.Data);
 | 
					                var ocelotConfig = await ocelotConfigurationCreator.Create(fileConfigFromConsul.Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(ocelotConfig.IsError)
 | 
					                if(ocelotConfig.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return new ErrorResponse(ocelotConfig.Errors);
 | 
					                    return new ErrorResponse(ocelotConfig.Errors);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                config = await ocelotConfigurationRepository.AddOrReplace(ocelotConfig.Data);
 | 
					                config = await ocelotConfigurationRepository.AddOrReplace(ocelotConfig.Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (config.IsError)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return new ErrorResponse(config.Errors);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                //todo - this starts the poller if it has been registered...please this is so bad.
 | 
					                //todo - this starts the poller if it has been registered...please this is so bad.
 | 
				
			||||||
                var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller));
 | 
					                var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@
 | 
				
			|||||||
    <DebugSymbols>True</DebugSymbols>
 | 
					    <DebugSymbols>True</DebugSymbols>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  </PropertyGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.5" />
 | 
					     <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> 
 | 
				
			||||||
    <PackageReference Include="FluentValidation" Version="7.2.1" />
 | 
					    <PackageReference Include="FluentValidation" Version="7.2.1" />
 | 
				
			||||||
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0" />
 | 
					    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
using System.Net.Http;
 | 
					using System.Net.Http;
 | 
				
			||||||
using Ocelot.Configuration;
 | 
					using Ocelot.Configuration;
 | 
				
			||||||
using Ocelot.Logging;
 | 
					using Ocelot.Logging;
 | 
				
			||||||
@@ -8,17 +9,17 @@ namespace Ocelot.Requester
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class DelegatingHandlerHandlerProviderFactory : IDelegatingHandlerHandlerProviderFactory
 | 
					    public class DelegatingHandlerHandlerProviderFactory : IDelegatingHandlerHandlerProviderFactory
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly ITracingHandler _tracingHandler;
 | 
					        private readonly ITracingHandlerFactory _factory;
 | 
				
			||||||
        private readonly IOcelotLoggerFactory _loggerFactory;
 | 
					        private readonly IOcelotLoggerFactory _loggerFactory;
 | 
				
			||||||
        private readonly IDelegatingHandlerHandlerProvider _allRoutesProvider;
 | 
					        private readonly IDelegatingHandlerHandlerProvider _allRoutesProvider;
 | 
				
			||||||
        private readonly IQosProviderHouse _qosProviderHouse;
 | 
					        private readonly IQosProviderHouse _qosProviderHouse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DelegatingHandlerHandlerProviderFactory(IOcelotLoggerFactory loggerFactory, 
 | 
					        public DelegatingHandlerHandlerProviderFactory(IOcelotLoggerFactory loggerFactory, 
 | 
				
			||||||
            IDelegatingHandlerHandlerProvider allRoutesProvider, 
 | 
					            IDelegatingHandlerHandlerProvider allRoutesProvider,
 | 
				
			||||||
            ITracingHandler tracingHandler,
 | 
					            ITracingHandlerFactory factory,
 | 
				
			||||||
            IQosProviderHouse qosProviderHouse)
 | 
					            IQosProviderHouse qosProviderHouse)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _tracingHandler = tracingHandler;
 | 
					            _factory = factory;
 | 
				
			||||||
            _loggerFactory = loggerFactory;
 | 
					            _loggerFactory = loggerFactory;
 | 
				
			||||||
            _allRoutesProvider = allRoutesProvider;
 | 
					            _allRoutesProvider = allRoutesProvider;
 | 
				
			||||||
            _qosProviderHouse = qosProviderHouse;
 | 
					            _qosProviderHouse = qosProviderHouse;
 | 
				
			||||||
@@ -37,7 +38,7 @@ namespace Ocelot.Requester
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (request.HttpHandlerOptions.UseTracing)
 | 
					            if (request.HttpHandlerOptions.UseTracing)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                provider.Add(() => (DelegatingHandler)_tracingHandler);
 | 
					                provider.Add(() => (DelegatingHandler)_factory.Get());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (request.IsQos)
 | 
					            if (request.IsQos)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,10 @@ namespace Ocelot.Requester
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var provider = _house.Get(request);
 | 
					            var provider = _house.Get(request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var handlers = provider.Data.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //todo handle error
 | 
					            //todo handle error
 | 
				
			||||||
            provider.Data.Get()
 | 
					            handlers
 | 
				
			||||||
                .Select(handler => handler)
 | 
					                .Select(handler => handler)
 | 
				
			||||||
                .Reverse()
 | 
					                .Reverse()
 | 
				
			||||||
                .ToList()
 | 
					                .ToList()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								src/Ocelot/Requester/ITracingHandlerFactory.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/Ocelot/Requester/ITracingHandlerFactory.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					namespace Ocelot.Requester
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface ITracingHandlerFactory
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ITracingHandler Get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,11 +12,6 @@ namespace Ocelot.Requester
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class NoTracingHandler : DelegatingHandler, ITracingHandler
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler
 | 
					    public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly IServiceTracer _tracer;
 | 
					        private readonly IServiceTracer _tracer;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								src/Ocelot/Requester/TracingHandlerFactory.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/Ocelot/Requester/TracingHandlerFactory.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					using Butterfly.Client.Tracing;
 | 
				
			||||||
 | 
					using Butterfly.OpenTracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.Requester
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class TracingHandlerFactory : ITracingHandlerFactory
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IServiceTracer _tracer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TracingHandlerFactory(IServiceTracer tracer)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _tracer = tracer;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ITracingHandler Get()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new OcelotHttpTracingHandler(_tracer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class FakeServiceTracer : IServiceTracer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public ITracer Tracer { get; }
 | 
				
			||||||
 | 
					        public string ServiceName { get; }
 | 
				
			||||||
 | 
					        public string Environment { get; }
 | 
				
			||||||
 | 
					        public string Identity { get; }
 | 
				
			||||||
 | 
					        public ISpan Start(ISpanBuilder spanBuilder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new System.NotImplementedException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										225
									
								
								test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,225 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Ocelot.Configuration.File;
 | 
				
			||||||
 | 
					using Shouldly;
 | 
				
			||||||
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					using Butterfly.Client.AspNetCore;
 | 
				
			||||||
 | 
					using static Rafty.Infrastructure.Wait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.AcceptanceTests
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class ButterflyTracingTests : IDisposable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private IWebHost _serviceOneBuilder;
 | 
				
			||||||
 | 
					        private IWebHost _serviceTwoBuilder;
 | 
				
			||||||
 | 
					        private IWebHost _fakeButterfly;
 | 
				
			||||||
 | 
					        private readonly Steps _steps;
 | 
				
			||||||
 | 
					        private string _downstreamPathOne;
 | 
				
			||||||
 | 
					        private string _downstreamPathTwo;
 | 
				
			||||||
 | 
					        private int _butterflyCalled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ButterflyTracingTests()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _steps = new Steps();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_forward_tracing_information_from_ocelot_and_downstream_services()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var configuration = new FileConfiguration
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ReRoutes = new List<FileReRoute>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        new FileReRoute
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            DownstreamPathTemplate = "/api/values",
 | 
				
			||||||
 | 
					                            DownstreamScheme = "http",
 | 
				
			||||||
 | 
					                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                new FileHostAndPort
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    Host = "localhost",
 | 
				
			||||||
 | 
					                                    Port = 51887,
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            UpstreamPathTemplate = "/api001/values",
 | 
				
			||||||
 | 
					                            UpstreamHttpMethod = new List<string> { "Get" },
 | 
				
			||||||
 | 
					                            HttpHandlerOptions = new FileHttpHandlerOptions
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                UseTracing  = true
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            QoSOptions = new FileQoSOptions
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                ExceptionsAllowedBeforeBreaking = 3,
 | 
				
			||||||
 | 
					                                DurationOfBreak = 10,
 | 
				
			||||||
 | 
					                                TimeoutValue = 5000
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        new FileReRoute
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            DownstreamPathTemplate = "/api/values",
 | 
				
			||||||
 | 
					                            DownstreamScheme = "http",
 | 
				
			||||||
 | 
					                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                new FileHostAndPort
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    Host = "localhost",
 | 
				
			||||||
 | 
					                                    Port = 51888,
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            UpstreamPathTemplate = "/api002/values",
 | 
				
			||||||
 | 
					                            UpstreamHttpMethod = new List<string> { "Get" },
 | 
				
			||||||
 | 
					                            HttpHandlerOptions = new FileHttpHandlerOptions
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                UseTracing  = true
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            QoSOptions = new FileQoSOptions
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                ExceptionsAllowedBeforeBreaking = 3,
 | 
				
			||||||
 | 
					                                DurationOfBreak = 10,
 | 
				
			||||||
 | 
					                                TimeoutValue = 5000
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var butterflyUrl = "http://localhost:9618";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.Given(x => GivenServiceOneIsRunning("http://localhost:51887", "/api/values", 200, "Hello from Laura", butterflyUrl))
 | 
				
			||||||
 | 
					                .And(x => GivenServiceTwoIsRunning("http://localhost:51888", "/api/values", 200, "Hello from Tom", butterflyUrl))
 | 
				
			||||||
 | 
					                .And(x => GivenFakeButterfly(butterflyUrl))
 | 
				
			||||||
 | 
					                .And(x => _steps.GivenThereIsAConfiguration(configuration))
 | 
				
			||||||
 | 
					                .And(x => _steps.GivenOcelotIsRunningUsingButterfly(butterflyUrl))
 | 
				
			||||||
 | 
					                .When(x => _steps.WhenIGetUrlOnTheApiGateway("/api001/values"))
 | 
				
			||||||
 | 
					                .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
				
			||||||
 | 
					                .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
 | 
				
			||||||
 | 
					                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/api002/values"))
 | 
				
			||||||
 | 
					                 .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
				
			||||||
 | 
					                 .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var commandOnAllStateMachines = WaitFor(5000).Until(() => _butterflyCalled == 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            commandOnAllStateMachines.ShouldBeTrue();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenServiceOneIsRunning(string baseUrl, string basePath, int statusCode, string responseBody, string butterflyUrl)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _serviceOneBuilder = new WebHostBuilder()
 | 
				
			||||||
 | 
					                .UseUrls(baseUrl)
 | 
				
			||||||
 | 
					                .UseKestrel()
 | 
				
			||||||
 | 
					                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
				
			||||||
 | 
					                .UseIISIntegration()
 | 
				
			||||||
 | 
					                .ConfigureServices(services => {
 | 
				
			||||||
 | 
					                    services.AddButterfly(option =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        option.CollectorUrl = butterflyUrl;
 | 
				
			||||||
 | 
					                        option.Service = "Service One";
 | 
				
			||||||
 | 
					                        option.IgnoredRoutesRegexPatterns = new string[0];
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Configure(app =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    app.UsePathBase(basePath);
 | 
				
			||||||
 | 
					                    app.Run(async context =>
 | 
				
			||||||
 | 
					                    {   
 | 
				
			||||||
 | 
					                        _downstreamPathOne = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if(_downstreamPathOne != basePath)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            context.Response.StatusCode = statusCode;
 | 
				
			||||||
 | 
					                            await context.Response.WriteAsync("downstream path didnt match base path");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            context.Response.StatusCode = statusCode;
 | 
				
			||||||
 | 
					                            await context.Response.WriteAsync(responseBody);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _serviceOneBuilder.Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenFakeButterfly(string baseUrl)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _fakeButterfly = new WebHostBuilder()
 | 
				
			||||||
 | 
					                .UseUrls(baseUrl)
 | 
				
			||||||
 | 
					                .UseKestrel()
 | 
				
			||||||
 | 
					                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
				
			||||||
 | 
					                .UseIISIntegration()
 | 
				
			||||||
 | 
					                .Configure(app =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    app.Run(async context =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        _butterflyCalled++;
 | 
				
			||||||
 | 
					                        await context.Response.WriteAsync("OK...");
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _fakeButterfly.Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenServiceTwoIsRunning(string baseUrl, string basePath, int statusCode, string responseBody, string butterflyUrl)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _serviceTwoBuilder = new WebHostBuilder()
 | 
				
			||||||
 | 
					                .UseUrls(baseUrl)
 | 
				
			||||||
 | 
					                .UseKestrel()
 | 
				
			||||||
 | 
					                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
				
			||||||
 | 
					                .UseIISIntegration()
 | 
				
			||||||
 | 
					                .ConfigureServices(services => {
 | 
				
			||||||
 | 
					                    services.AddButterfly(option =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        option.CollectorUrl = butterflyUrl;
 | 
				
			||||||
 | 
					                        option.Service = "Service Two";
 | 
				
			||||||
 | 
					                        option.IgnoredRoutesRegexPatterns = new string[0];
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Configure(app =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    app.UsePathBase(basePath);
 | 
				
			||||||
 | 
					                    app.Run(async context =>
 | 
				
			||||||
 | 
					                    {   
 | 
				
			||||||
 | 
					                        _downstreamPathTwo = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if(_downstreamPathTwo != basePath)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            context.Response.StatusCode = statusCode;
 | 
				
			||||||
 | 
					                            await context.Response.WriteAsync("downstream path didnt match base path");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            context.Response.StatusCode = statusCode;
 | 
				
			||||||
 | 
					                            await context.Response.WriteAsync(responseBody);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _serviceTwoBuilder.Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal void ThenTheDownstreamUrlPathShouldBe(string expectedDownstreamPathOne, string expectedDownstreamPath)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _downstreamPathOne.ShouldBe(expectedDownstreamPathOne);
 | 
				
			||||||
 | 
					            _downstreamPathTwo.ShouldBe(expectedDownstreamPath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _serviceOneBuilder?.Dispose();
 | 
				
			||||||
 | 
					            _serviceTwoBuilder?.Dispose();
 | 
				
			||||||
 | 
					            _fakeButterfly?.Dispose();
 | 
				
			||||||
 | 
					            _steps.Dispose();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,13 +4,10 @@ using System.Diagnostics;
 | 
				
			|||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Net;
 | 
					using System.Net;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using System.Threading;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Builder;
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
using Microsoft.AspNetCore.Hosting;
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
using Newtonsoft.Json;
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
using Ocelot.Configuration;
 | 
					 | 
				
			||||||
using Ocelot.Configuration.Builder;
 | 
					 | 
				
			||||||
using Ocelot.Configuration.File;
 | 
					using Ocelot.Configuration.File;
 | 
				
			||||||
using TestStack.BDDfy;
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
using Xunit;
 | 
					using Xunit;
 | 
				
			||||||
@@ -275,7 +272,11 @@ namespace Ocelot.AcceptanceTests
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void GivenIWaitForTheConfigToReplicateToOcelot()
 | 
					        private void GivenIWaitForTheConfigToReplicateToOcelot()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Thread.Sleep(10000);
 | 
					            var stopWatch = Stopwatch.StartNew();
 | 
				
			||||||
 | 
					            while (stopWatch.ElapsedMilliseconds < 10000)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                //do nothing!
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenTheConsulConfigurationIs(FileConfiguration config)
 | 
					        private void GivenTheConsulConfigurationIs(FileConfiguration config)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,53 +1,48 @@
 | 
				
			|||||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
					<Project Sdk="Microsoft.NET.Sdk">
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
  <PropertyGroup>
 | 
					    <VersionPrefix>0.0.0-dev</VersionPrefix>
 | 
				
			||||||
    <VersionPrefix>0.0.0-dev</VersionPrefix>
 | 
					    <TargetFramework>netcoreapp2.0</TargetFramework>
 | 
				
			||||||
    <TargetFramework>netcoreapp2.0</TargetFramework>
 | 
					    <RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
 | 
				
			||||||
    <RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
 | 
					    <AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
 | 
				
			||||||
    <AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
 | 
					    <OutputType>Exe</OutputType>
 | 
				
			||||||
    <OutputType>Exe</OutputType>
 | 
					    <PackageId>Ocelot.AcceptanceTests</PackageId>
 | 
				
			||||||
    <PackageId>Ocelot.AcceptanceTests</PackageId>
 | 
					    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
 | 
				
			||||||
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
 | 
					    <RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
 | 
				
			||||||
    <RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
 | 
					    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
 | 
				
			||||||
    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
 | 
					    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
 | 
				
			||||||
    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
 | 
					    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
 | 
				
			||||||
    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
 | 
					  </PropertyGroup>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <None Update="configuration.json;appsettings.json">
 | 
				
			||||||
  <ItemGroup>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    <None Update="configuration.json;appsettings.json">
 | 
					    </None>
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					  </ItemGroup>
 | 
				
			||||||
    </None>
 | 
					  <ItemGroup>
 | 
				
			||||||
  </ItemGroup>
 | 
					    <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Ocelot.ManualTest\Ocelot.ManualTest.csproj" />
 | 
				
			||||||
  <ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
    <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
 | 
					  <ItemGroup>
 | 
				
			||||||
    <ProjectReference Include="..\Ocelot.ManualTest\Ocelot.ManualTest.csproj" />
 | 
					    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					    <PackageReference Include="CacheManager.Serialization.Json" Version="1.1.1" />
 | 
				
			||||||
  <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
				
			||||||
</ItemGroup>
 | 
					    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" />
 | 
				
			||||||
  <ItemGroup>
 | 
					    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
 | 
				
			||||||
    <PackageReference Include="CacheManager.Serialization.Json" Version="1.1.1" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
					    <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
					    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
					    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
					    <PackageReference Include="Consul" Version="0.7.2.3" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
 | 
					    <PackageReference Include="xunit" Version="2.3.1" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
 | 
					     <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> 
 | 
				
			||||||
    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
					  </ItemGroup>
 | 
				
			||||||
    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
					</Project>
 | 
				
			||||||
    <PackageReference Include="Consul" Version="0.7.2.3" />
 | 
					 | 
				
			||||||
    <PackageReference Include="xunit" Version="2.3.1" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</Project>
 | 
					 | 
				
			||||||
@@ -26,6 +26,8 @@ using Ocelot.ServiceDiscovery;
 | 
				
			|||||||
using Shouldly;
 | 
					using Shouldly;
 | 
				
			||||||
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
 | 
					using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
 | 
				
			||||||
using Ocelot.AcceptanceTests.Caching;
 | 
					using Ocelot.AcceptanceTests.Caching;
 | 
				
			||||||
 | 
					using Butterfly.Client.AspNetCore;
 | 
				
			||||||
 | 
					using Butterfly.Client.Tracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.AcceptanceTests
 | 
					namespace Ocelot.AcceptanceTests
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -105,6 +107,49 @@ namespace Ocelot.AcceptanceTests
 | 
				
			|||||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
					            _ocelotClient = _ocelotServer.CreateClient();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal void GivenOcelotIsRunningUsingButterfly(string butterflyUrl)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _webHostBuilder = new WebHostBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _webHostBuilder
 | 
				
			||||||
 | 
					                .ConfigureAppConfiguration((hostingContext, config) =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
 | 
				
			||||||
 | 
					                    var env = hostingContext.HostingEnvironment;
 | 
				
			||||||
 | 
					                    config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
 | 
				
			||||||
 | 
					                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
 | 
				
			||||||
 | 
					                    config.AddJsonFile("configuration.json");
 | 
				
			||||||
 | 
					                    config.AddEnvironmentVariables();
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .ConfigureServices(s =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    s.AddOcelot()
 | 
				
			||||||
 | 
					                    .AddOpenTracing(option =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        //this is the url that the butterfly collector server is running on...
 | 
				
			||||||
 | 
					                        option.CollectorUrl = butterflyUrl;
 | 
				
			||||||
 | 
					                        option.Service = "Ocelot";
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Configure(app =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    app.Use(async (context, next) =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        await next.Invoke();
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    app.UseOcelot().Wait();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _ocelotServer = new TestServer(_webHostBuilder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _ocelotClient = _ocelotServer.CreateClient();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					        public void GivenIHaveAddedXForwardedForHeader(string value)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _ocelotClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Forwarded-For", value);
 | 
				
			||||||
 | 
					        }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void GivenOcelotIsRunningWithMiddleareBeforePipeline<T>(Func<object, Task> callback)
 | 
					        public void GivenOcelotIsRunningWithMiddleareBeforePipeline<T>(Func<object, Task> callback)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _webHostBuilder = new WebHostBuilder();
 | 
					            _webHostBuilder = new WebHostBuilder();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,25 +25,24 @@ namespace Ocelot.ManualTest
 | 
				
			|||||||
                        .AddEnvironmentVariables();
 | 
					                        .AddEnvironmentVariables();
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .ConfigureServices(s => {
 | 
					                .ConfigureServices(s => {
 | 
				
			||||||
 | 
					                     s.AddAuthentication()
 | 
				
			||||||
                    s.AddAuthentication()
 | 
					 | 
				
			||||||
                        .AddJwtBearer("TestKey", x =>
 | 
					                        .AddJwtBearer("TestKey", x =>
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            x.Authority = "test";
 | 
					                            x.Authority = "test";
 | 
				
			||||||
                            x.Audience = "test";
 | 
					                            x.Audience = "test";
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    s.AddOcelot()
 | 
					                     s.AddOcelot()
 | 
				
			||||||
                        .AddCacheManager(x =>
 | 
					                         .AddCacheManager(x =>
 | 
				
			||||||
                        {
 | 
					                         {
 | 
				
			||||||
                            x.WithDictionaryHandle();
 | 
					                             x.WithDictionaryHandle();
 | 
				
			||||||
                        })
 | 
					                         })
 | 
				
			||||||
                        .AddOpenTracing(option =>
 | 
					                         .AddOpenTracing(option =>
 | 
				
			||||||
                        {
 | 
					                         {
 | 
				
			||||||
                            option.CollectorUrl = "http://localhost:9618";
 | 
					                             option.CollectorUrl = "http://localhost:9618";
 | 
				
			||||||
                            option.Service = "Ocelot.ManualTest";
 | 
					                             option.Service = "Ocelot.ManualTest";
 | 
				
			||||||
                        })
 | 
					                         })
 | 
				
			||||||
                        .AddAdministration("/administration", "secret");
 | 
					                         .AddAdministration("/administration", "secret");
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .ConfigureLogging((hostingContext, logging) =>
 | 
					                .ConfigureLogging((hostingContext, logging) =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,13 +8,13 @@
 | 
				
			|||||||
      "DownstreamHostAndPorts": [
 | 
					      "DownstreamHostAndPorts": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "Host": "localhost",
 | 
					          "Host": "localhost",
 | 
				
			||||||
          "Port": 5001
 | 
					          "Port": 5007
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "HttpHandlerOptions": {
 | 
					      "HttpHandlerOptions": {
 | 
				
			||||||
        "AllowAutoRedirect": true,
 | 
					        "AllowAutoRedirect": true,
 | 
				
			||||||
        "UseCookieContainer": true,
 | 
					        "UseCookieContainer": true,
 | 
				
			||||||
        "UseTracing": false
 | 
					        "UseTracing": true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,6 +50,7 @@
 | 
				
			|||||||
    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
					    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
				
			||||||
    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
					    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
				
			||||||
    <PackageReference Include="xunit" Version="2.3.1" />
 | 
					    <PackageReference Include="xunit" Version="2.3.1" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</Project>
 | 
					</Project>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,13 +23,15 @@ namespace Ocelot.UnitTests.Requester
 | 
				
			|||||||
        private Response<IDelegatingHandlerHandlerProvider> _provider;
 | 
					        private Response<IDelegatingHandlerHandlerProvider> _provider;
 | 
				
			||||||
        private readonly Mock<IDelegatingHandlerHandlerProvider> _allRoutesProvider;
 | 
					        private readonly Mock<IDelegatingHandlerHandlerProvider> _allRoutesProvider;
 | 
				
			||||||
        private readonly Mock<IQosProviderHouse> _qosProviderHouse;
 | 
					        private readonly Mock<IQosProviderHouse> _qosProviderHouse;
 | 
				
			||||||
 | 
					        private readonly Mock<ITracingHandlerFactory> _tracingFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DelegatingHandlerHandlerProviderFactoryTests()
 | 
					        public DelegatingHandlerHandlerProviderFactoryTests()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            _tracingFactory = new Mock<ITracingHandlerFactory>();
 | 
				
			||||||
            _qosProviderHouse = new Mock<IQosProviderHouse>();
 | 
					            _qosProviderHouse = new Mock<IQosProviderHouse>();
 | 
				
			||||||
            _allRoutesProvider = new Mock<IDelegatingHandlerHandlerProvider>();
 | 
					            _allRoutesProvider = new Mock<IDelegatingHandlerHandlerProvider>();
 | 
				
			||||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
					            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
				
			||||||
            _factory = new DelegatingHandlerHandlerProviderFactory(_loggerFactory.Object, _allRoutesProvider.Object, null, _qosProviderHouse.Object);
 | 
					            _factory = new DelegatingHandlerHandlerProviderFactory(_loggerFactory.Object, _allRoutesProvider.Object, _tracingFactory.Object, _qosProviderHouse.Object);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
 | 
					        private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					using Butterfly.Client.Tracing;
 | 
				
			||||||
 | 
					using Moq;
 | 
				
			||||||
 | 
					using Ocelot.Requester;
 | 
				
			||||||
 | 
					using Shouldly;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.UnitTests.Requester
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class TracingHandlerFactoryTests
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private TracingHandlerFactory _factory;
 | 
				
			||||||
 | 
					        private Mock<IServiceTracer> _tracer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TracingHandlerFactoryTests()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _tracer = new Mock<IServiceTracer>();
 | 
				
			||||||
 | 
					            _factory = new TracingHandlerFactory(_tracer.Object);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_return()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var handler = _factory.Get();
 | 
				
			||||||
 | 
					            handler.ShouldBeOfType<OcelotHttpTracingHandler>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user