diff --git a/docs/favicon.ico b/docs/favicon.ico index ee470e42..5e606f74 100644 Binary files a/docs/favicon.ico and b/docs/favicon.ico differ diff --git a/docs/features/administration.rst b/docs/features/administration.rst index 425c958e..dd08feab 100644 --- a/docs/features/administration.rst +++ b/docs/features/administration.rst @@ -21,7 +21,7 @@ All you need to do to hook into your own IdentityServer is add the following to }; services - .AddOcelot(Configuration) + .AddOcelot() .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) { services - .AddOcelot(Configuration) + .AddOcelot() .AddAdministration("/administration", "secret"); } diff --git a/docs/features/authentication.rst b/docs/features/authentication.rst index dd78fcfa..78aa890f 100644 --- a/docs/features/authentication.rst +++ b/docs/features/authentication.rst @@ -63,7 +63,7 @@ If you want to authenticate using JWT tokens maybe from a provider like Auth0 yo x.Audience = "test"; }); - services.AddOcelot(Configuration); + services.AddOcelot(); } 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() .AddIdentityServerAuthentication(authenticationProviderKey, options); - services.AddOcelot(Configuration); + services.AddOcelot(); } Then map the authentication provider key to a ReRoute in your configuration e.g. diff --git a/docs/features/configuration.rst b/docs/features/configuration.rst index 5aa054f8..93cae138 100644 --- a/docs/features/configuration.rst +++ b/docs/features/configuration.rst @@ -109,7 +109,7 @@ If you add the following when you register your services Ocelot will attempt to .. code-block:: csharp services - .AddOcelot(Configuration) + .AddOcelot() .AddStoreOcelotConfigurationInConsul(); You also need to add the following to your configuration.json. This is how Ocelot diff --git a/docs/features/raft.rst b/docs/features/raft.rst index 45ea59f2..dd0cf031 100644 --- a/docs/features/raft.rst +++ b/docs/features/raft.rst @@ -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) { services - .AddOcelot(Configuration) + .AddOcelot() .AddAdministration("/administration", "secret") .AddRafty(); } diff --git a/docs/features/tracing.rst b/docs/features/tracing.rst index a30ea741..0a896d45 100644 --- a/docs/features/tracing.rst +++ b/docs/features/tracing.rst @@ -12,7 +12,7 @@ In your ConfigureServices method .. code-block:: csharp services - .AddOcelot(Configuration) + .AddOcelot() .AddOpenTracing(option => { //this is the url that the butterfly collector server is running on... diff --git a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs index 8274af2f..7e78b3aa 100644 --- a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs +++ b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs @@ -11,11 +11,11 @@ namespace Ocelot.Configuration.Repository { public class ConsulFileConfigurationPoller : IDisposable { - private IOcelotLogger _logger; - private IFileConfigurationRepository _repo; - private IFileConfigurationSetter _setter; + private readonly IOcelotLogger _logger; + private readonly IFileConfigurationRepository _repo; + private readonly IFileConfigurationSetter _setter; private string _previousAsJson; - private Timer _timer; + private readonly Timer _timer; private bool _polling; public ConsulFileConfigurationPoller(IOcelotLoggerFactory factory, IFileConfigurationRepository repo, IFileConfigurationSetter setter) @@ -77,4 +77,4 @@ namespace Ocelot.Configuration.Repository _timer.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/DependencyInjection/OcelotBuilder.cs b/src/Ocelot/DependencyInjection/OcelotBuilder.cs index 3dde5d54..f4192713 100644 --- a/src/Ocelot/DependencyInjection/OcelotBuilder.cs +++ b/src/Ocelot/DependencyInjection/OcelotBuilder.cs @@ -1,3 +1,4 @@ +using Butterfly.Client.Tracing; using Microsoft.Extensions.Options; using Ocelot.Middleware.Multiplexer; @@ -146,10 +147,14 @@ namespace Ocelot.DependencyInjection //these get picked out later and added to http request _provider = new DelegatingHandlerHandlerProvider(); - _services.TryAddSingleton(_provider); - _services.AddTransient(); + _services.TryAddSingleton(_provider); _services.TryAddSingleton(); _services.TryAddSingleton(); + _services.AddSingleton(); + + // We add this here so that we can always inject something into the factory for IoC.. + _services.AddSingleton(); + } public IOcelotAdministrationBuilder AddAdministration(string path, string secret) @@ -192,7 +197,8 @@ namespace Ocelot.DependencyInjection public IOcelotBuilder AddOpenTracing(Action settings) { - _services.AddTransient(); + // Earlier we add FakeServiceTracer and need to remove it here before we add butterfly + _services.RemoveAll(); _services.AddButterfly(settings); return this; } diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index 9dbb7c22..541a8e93 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -173,23 +173,34 @@ var ocelotConfigurationRepository = (IOcelotConfigurationRepository) builder.ApplicationServices.GetService( typeof(IOcelotConfigurationRepository)); + var ocelotConfigurationCreator = (IOcelotConfigurationCreator) builder.ApplicationServices.GetService( typeof(IOcelotConfigurationCreator)); var fileConfigFromConsul = await consulFileConfigRepo.Get(); + if (fileConfigFromConsul.Data == null) { config = await setter.Set(fileConfig.Value); + var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller)); } else { var ocelotConfig = await ocelotConfigurationCreator.Create(fileConfigFromConsul.Data); + if(ocelotConfig.IsError) { return new ErrorResponse(ocelotConfig.Errors); } + 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. var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller)); } diff --git a/src/Ocelot/Ocelot.csproj b/src/Ocelot/Ocelot.csproj index eb4ce773..62552bed 100644 --- a/src/Ocelot/Ocelot.csproj +++ b/src/Ocelot/Ocelot.csproj @@ -23,7 +23,7 @@ True - + diff --git a/src/Ocelot/Requester/DelegatingHandlerHandlerProviderFactory.cs b/src/Ocelot/Requester/DelegatingHandlerHandlerProviderFactory.cs index c6267123..468b6013 100644 --- a/src/Ocelot/Requester/DelegatingHandlerHandlerProviderFactory.cs +++ b/src/Ocelot/Requester/DelegatingHandlerHandlerProviderFactory.cs @@ -1,3 +1,4 @@ +using System; using System.Net.Http; using Ocelot.Configuration; using Ocelot.Logging; @@ -8,17 +9,17 @@ namespace Ocelot.Requester { public class DelegatingHandlerHandlerProviderFactory : IDelegatingHandlerHandlerProviderFactory { - private readonly ITracingHandler _tracingHandler; + private readonly ITracingHandlerFactory _factory; private readonly IOcelotLoggerFactory _loggerFactory; private readonly IDelegatingHandlerHandlerProvider _allRoutesProvider; private readonly IQosProviderHouse _qosProviderHouse; public DelegatingHandlerHandlerProviderFactory(IOcelotLoggerFactory loggerFactory, - IDelegatingHandlerHandlerProvider allRoutesProvider, - ITracingHandler tracingHandler, + IDelegatingHandlerHandlerProvider allRoutesProvider, + ITracingHandlerFactory factory, IQosProviderHouse qosProviderHouse) { - _tracingHandler = tracingHandler; + _factory = factory; _loggerFactory = loggerFactory; _allRoutesProvider = allRoutesProvider; _qosProviderHouse = qosProviderHouse; @@ -37,7 +38,7 @@ namespace Ocelot.Requester if (request.HttpHandlerOptions.UseTracing) { - provider.Add(() => (DelegatingHandler)_tracingHandler); + provider.Add(() => (DelegatingHandler)_factory.Get()); } if (request.IsQos) diff --git a/src/Ocelot/Requester/HttpClientBuilder.cs b/src/Ocelot/Requester/HttpClientBuilder.cs index 9c832b1d..2d3a0f36 100644 --- a/src/Ocelot/Requester/HttpClientBuilder.cs +++ b/src/Ocelot/Requester/HttpClientBuilder.cs @@ -26,8 +26,10 @@ namespace Ocelot.Requester { var provider = _house.Get(request); + var handlers = provider.Data.Get(); + //todo handle error - provider.Data.Get() + handlers .Select(handler => handler) .Reverse() .ToList() diff --git a/src/Ocelot/Requester/ITracingHandlerFactory.cs b/src/Ocelot/Requester/ITracingHandlerFactory.cs new file mode 100644 index 00000000..6f0f6619 --- /dev/null +++ b/src/Ocelot/Requester/ITracingHandlerFactory.cs @@ -0,0 +1,7 @@ +namespace Ocelot.Requester +{ + public interface ITracingHandlerFactory + { + ITracingHandler Get(); + } +} diff --git a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs index ff588fe8..e2658c7f 100644 --- a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs +++ b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs @@ -12,11 +12,6 @@ namespace Ocelot.Requester { } - public class NoTracingHandler : DelegatingHandler, ITracingHandler - { - - } - public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler { private readonly IServiceTracer _tracer; diff --git a/src/Ocelot/Requester/TracingHandlerFactory.cs b/src/Ocelot/Requester/TracingHandlerFactory.cs new file mode 100644 index 00000000..5cb72a79 --- /dev/null +++ b/src/Ocelot/Requester/TracingHandlerFactory.cs @@ -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(); + } + } +} diff --git a/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs b/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs new file mode 100644 index 00000000..84346985 --- /dev/null +++ b/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs @@ -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 + { + new FileReRoute + { + DownstreamPathTemplate = "/api/values", + DownstreamScheme = "http", + DownstreamHostAndPorts = new List + { + new FileHostAndPort + { + Host = "localhost", + Port = 51887, + } + }, + UpstreamPathTemplate = "/api001/values", + UpstreamHttpMethod = new List { "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 + { + new FileHostAndPort + { + Host = "localhost", + Port = 51888, + } + }, + UpstreamPathTemplate = "/api002/values", + UpstreamHttpMethod = new List { "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(); + } + } +} diff --git a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs index c95d6323..db617718 100644 --- a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs +++ b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs @@ -4,13 +4,10 @@ using System.Diagnostics; using System.IO; using System.Net; using System.Text; -using System.Threading; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; -using Ocelot.Configuration; -using Ocelot.Configuration.Builder; using Ocelot.Configuration.File; using TestStack.BDDfy; using Xunit; @@ -275,7 +272,11 @@ namespace Ocelot.AcceptanceTests private void GivenIWaitForTheConfigToReplicateToOcelot() { - Thread.Sleep(10000); + var stopWatch = Stopwatch.StartNew(); + while (stopWatch.ElapsedMilliseconds < 10000) + { + //do nothing! + } } private void GivenTheConsulConfigurationIs(FileConfiguration config) diff --git a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj index ab7ae7ce..396eb403 100644 --- a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj +++ b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj @@ -1,53 +1,48 @@ - - - - 0.0.0-dev - netcoreapp2.0 - 2.0.0 - Ocelot.AcceptanceTests - Exe - Ocelot.AcceptanceTests - true - osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64 - false - false - false - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 0.0.0-dev + netcoreapp2.0 + 2.0.0 + Ocelot.AcceptanceTests + Exe + Ocelot.AcceptanceTests + true + osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64 + false + false + false + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Ocelot.AcceptanceTests/Steps.cs b/test/Ocelot.AcceptanceTests/Steps.cs index b7f3e6ab..6a6fa3c4 100644 --- a/test/Ocelot.AcceptanceTests/Steps.cs +++ b/test/Ocelot.AcceptanceTests/Steps.cs @@ -26,6 +26,8 @@ using Ocelot.ServiceDiscovery; using Shouldly; using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder; using Ocelot.AcceptanceTests.Caching; +using Butterfly.Client.AspNetCore; +using Butterfly.Client.Tracing; namespace Ocelot.AcceptanceTests { @@ -105,6 +107,49 @@ namespace Ocelot.AcceptanceTests _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(Func callback) { _webHostBuilder = new WebHostBuilder(); diff --git a/test/Ocelot.ManualTest/Program.cs b/test/Ocelot.ManualTest/Program.cs index 8cb4e917..4e728d3d 100644 --- a/test/Ocelot.ManualTest/Program.cs +++ b/test/Ocelot.ManualTest/Program.cs @@ -25,25 +25,24 @@ namespace Ocelot.ManualTest .AddEnvironmentVariables(); }) .ConfigureServices(s => { - - s.AddAuthentication() + s.AddAuthentication() .AddJwtBearer("TestKey", x => { x.Authority = "test"; x.Audience = "test"; }); - s.AddOcelot() - .AddCacheManager(x => - { - x.WithDictionaryHandle(); - }) - .AddOpenTracing(option => - { - option.CollectorUrl = "http://localhost:9618"; - option.Service = "Ocelot.ManualTest"; - }) - .AddAdministration("/administration", "secret"); + s.AddOcelot() + .AddCacheManager(x => + { + x.WithDictionaryHandle(); + }) + .AddOpenTracing(option => + { + option.CollectorUrl = "http://localhost:9618"; + option.Service = "Ocelot.ManualTest"; + }) + .AddAdministration("/administration", "secret"); }) .ConfigureLogging((hostingContext, logging) => { diff --git a/test/Ocelot.ManualTest/configuration.json b/test/Ocelot.ManualTest/configuration.json index 98ce38b8..ba34d4e5 100644 --- a/test/Ocelot.ManualTest/configuration.json +++ b/test/Ocelot.ManualTest/configuration.json @@ -8,13 +8,13 @@ "DownstreamHostAndPorts": [ { "Host": "localhost", - "Port": 5001 + "Port": 5007 } ], "HttpHandlerOptions": { "AllowAutoRedirect": true, "UseCookieContainer": true, - "UseTracing": false + "UseTracing": true } }, { diff --git a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj index 7993644f..fcc2c7e2 100644 --- a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj +++ b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj @@ -50,6 +50,7 @@ + diff --git a/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs b/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs index 8f861260..e6942681 100644 --- a/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs +++ b/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs @@ -23,13 +23,15 @@ namespace Ocelot.UnitTests.Requester private Response _provider; private readonly Mock _allRoutesProvider; private readonly Mock _qosProviderHouse; + private readonly Mock _tracingFactory; public DelegatingHandlerHandlerProviderFactoryTests() { + _tracingFactory = new Mock(); _qosProviderHouse = new Mock(); _allRoutesProvider = new Mock(); _loggerFactory = new Mock(); - _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 qosProvider) diff --git a/test/Ocelot.UnitTests/Requester/TracingHandlerFactoryTests.cs b/test/Ocelot.UnitTests/Requester/TracingHandlerFactoryTests.cs new file mode 100644 index 00000000..e8196966 --- /dev/null +++ b/test/Ocelot.UnitTests/Requester/TracingHandlerFactoryTests.cs @@ -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 _tracer; + + public TracingHandlerFactoryTests() + { + _tracer = new Mock(); + _factory = new TracingHandlerFactory(_tracer.Object); + } + + [Fact] + public void should_return() + { + var handler = _factory.Get(); + handler.ShouldBeOfType(); + } + } +} \ No newline at end of file