mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-20 08:22: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:
parent
18c34aa998
commit
9f1fb002c1
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)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Butterfly.Client.Tracing;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Ocelot.Middleware.Multiplexer;
|
using Ocelot.Middleware.Multiplexer;
|
||||||
|
|
||||||
@ -147,9 +148,13 @@ 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,5 +1,4 @@
|
|||||||
<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>
|
||||||
@ -13,22 +12,18 @@
|
|||||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="configuration.json;appsettings.json">
|
<None Update="configuration.json;appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||||
<ProjectReference Include="..\Ocelot.ManualTest\Ocelot.ManualTest.csproj" />
|
<ProjectReference Include="..\Ocelot.ManualTest\Ocelot.ManualTest.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.1" />
|
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
|
||||||
@ -48,6 +43,6 @@
|
|||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="Consul" Version="0.7.2.3" />
|
<PackageReference Include="Consul" Version="0.7.2.3" />
|
||||||
<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>
|
@ -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>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user