mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	Feature/store configuraton json idented (#328)
* messing around with benchmark.net.seems Ocelot adds about 2ms to a request..lets make this less? :) * #326 store json indented so it looks nice :P
This commit is contained in:
		@@ -163,7 +163,7 @@ requests. This would also mean that subsequent requests dont use the cookies fro
 | 
			
		||||
UseCookieContainer to true unless you have a really really good reason. Just look at your response headers and forward the cookies back with your next request! 
 | 
			
		||||
 | 
			
		||||
SSL Errors
 | 
			
		||||
----------
 | 
			
		||||
^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Id you want to ignore SSL warnings / errors set the following in your ReRoute config.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -69,18 +69,20 @@ In order to get this working add the following to ocelot.json..
 | 
			
		||||
        "Type": "Eureka"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
And following the guide `Here <https://steeltoe.io/docs/steeltoe-discovery/>`_ you may also need to add some stuff to appsettings.json. For example the json below
 | 
			
		||||
tells the steeltoe / pivotal services where to look for the service discovery server and if the service should register with it.
 | 
			
		||||
And following the guide `Here <https://steeltoe.io/docs/steeltoe-discovery/>`_ you may also need to add some stuff to appsettings.json. For example the json below tells the steeltoe / pivotal services where to look for the service discovery server and if the service should register with it.
 | 
			
		||||
 | 
			
		||||
.. code-block:: json
 | 
			
		||||
 | 
			
		||||
    "eureka": {
 | 
			
		||||
        "client": {
 | 
			
		||||
        "serviceUrl": "http://localhost:8761/eureka/",
 | 
			
		||||
        "shouldRegisterWithEureka": true
 | 
			
		||||
        "shouldRegisterWithEureka": false,
 | 
			
		||||
        "shouldFetchRegistry": true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
I am told that if shouldRegisterWithEureka is false then shouldFetchRegistry will defaut to true so you don't need it explicitly but left it in there.
 | 
			
		||||
 | 
			
		||||
Ocelot will now register all the necessary services when it starts up and if you have the json above will register itself with 
 | 
			
		||||
Eureka. One of the services polls Eureka every 30 seconds (default) and gets the latest service state and persists this in memory.
 | 
			
		||||
When Ocelot asks for a given service it is retrieved from memory so performance is not a big problem. Please note that this code
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
 | 
			
		||||
    public class ConsulFileConfigurationRepository : IFileConfigurationRepository
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConsulClient _consul;
 | 
			
		||||
        private readonly IConsulClient _consul;
 | 
			
		||||
        private const string OcelotConfiguration = "InternalConfiguration";
 | 
			
		||||
        private readonly Cache.IOcelotCache<FileConfiguration> _cache;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
 | 
			
		||||
        public async Task<Response> Set(FileConfiguration ocelotConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var json = JsonConvert.SerializeObject(ocelotConfiguration);
 | 
			
		||||
            var json = JsonConvert.SerializeObject(ocelotConfiguration, Formatting.Indented);
 | 
			
		||||
 | 
			
		||||
            var bytes = Encoding.UTF8.GetBytes(json);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
 | 
			
		||||
        public Task<Response> Set(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            string jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
            string jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration, Formatting.Indented);
 | 
			
		||||
 | 
			
		||||
            lock(_lock)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ namespace Ocelot.Infrastructure.Consul
 | 
			
		||||
{
 | 
			
		||||
    public class ConsulClientFactory : IConsulClientFactory
 | 
			
		||||
    {
 | 
			
		||||
        public ConsulClient Get(ConsulRegistryConfiguration config)
 | 
			
		||||
        public IConsulClient Get(ConsulRegistryConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            return new ConsulClient(c =>
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,6 @@ namespace Ocelot.Infrastructure.Consul
 | 
			
		||||
{
 | 
			
		||||
    public interface IConsulClientFactory
 | 
			
		||||
    {
 | 
			
		||||
        ConsulClient Get(ConsulRegistryConfiguration config);
 | 
			
		||||
        IConsulClient Get(ConsulRegistryConfiguration config);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace Ocelot.ServiceDiscovery.Providers
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConsulRegistryConfiguration _config;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly ConsulClient _consul;
 | 
			
		||||
        private readonly IConsulClient _consul;
 | 
			
		||||
        private const string VersionPrefix = "version-";
 | 
			
		||||
 | 
			
		||||
        public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
 | 
			
		||||
 
 | 
			
		||||
@@ -88,7 +88,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
        {
 | 
			
		||||
            var configurationPath = TestConfiguration.ConfigurationPath;
 | 
			
		||||
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration, Formatting.Indented);
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(configurationPath))
 | 
			
		||||
            {
 | 
			
		||||
@@ -100,7 +100,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
 | 
			
		||||
        public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration, string configurationPath)
 | 
			
		||||
        {
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration, Formatting.Indented);
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(configurationPath))
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										157
									
								
								test/Ocelot.Benchmarks/AllTheThingsBenchmarks.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								test/Ocelot.Benchmarks/AllTheThingsBenchmarks.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using BenchmarkDotNet.Attributes;
 | 
			
		||||
using BenchmarkDotNet.Columns;
 | 
			
		||||
using BenchmarkDotNet.Configs;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using BenchmarkDotNet.Attributes.Jobs;
 | 
			
		||||
using BenchmarkDotNet.Diagnosers;
 | 
			
		||||
using BenchmarkDotNet.Validators;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Benchmarks
 | 
			
		||||
{
 | 
			
		||||
    [Config(typeof(AllTheThingsBenchmarks))]
 | 
			
		||||
    public class AllTheThingsBenchmarks : ManualConfig
 | 
			
		||||
    {
 | 
			
		||||
        private IWebHost _service;
 | 
			
		||||
        private IWebHost _ocelot;
 | 
			
		||||
        private HttpClient _httpClient;
 | 
			
		||||
 | 
			
		||||
        public AllTheThingsBenchmarks()
 | 
			
		||||
        {
 | 
			
		||||
            Add(StatisticColumn.AllStatistics);
 | 
			
		||||
            Add(MemoryDiagnoser.Default);
 | 
			
		||||
            Add(BaselineValidator.FailOnError);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [GlobalSetup]
 | 
			
		||||
        public void SetUp()
 | 
			
		||||
        {
 | 
			
		||||
            var configuration = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ReRoutes = new List<FileReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileReRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamPathTemplate = "/",
 | 
			
		||||
                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                            {
 | 
			
		||||
                                new FileHostAndPort
 | 
			
		||||
                                {
 | 
			
		||||
                                    Host = "localhost",
 | 
			
		||||
                                    Port = 51879,
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            DownstreamScheme = "http",
 | 
			
		||||
                            UpstreamPathTemplate = "/",
 | 
			
		||||
                            UpstreamHttpMethod = new List<string> { "Get" },
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 201, string.Empty);
 | 
			
		||||
            GivenThereIsAConfiguration(configuration);
 | 
			
		||||
            GivenOcelotIsRunning("http://localhost:5000");
 | 
			
		||||
 | 
			
		||||
            _httpClient = new HttpClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Benchmark(Baseline = true)]
 | 
			
		||||
        public async Task Baseline()
 | 
			
		||||
        {
 | 
			
		||||
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:5000/");
 | 
			
		||||
            var response = await _httpClient.SendAsync(request);
 | 
			
		||||
            response.EnsureSuccessStatusCode();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // * Summary *
 | 
			
		||||
        // BenchmarkDotNet=v0.10.13, OS=macOS 10.12.6 (16G1212) [Darwin 16.7.0]
 | 
			
		||||
        // Intel Core i5-4278U CPU 2.60GHz (Haswell), 1 CPU, 4 logical cores and 2 physical cores
 | 
			
		||||
        // .NET Core SDK=2.1.4
 | 
			
		||||
        //   [Host]     : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
 | 
			
		||||
        //   DefaultJob : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
 | 
			
		||||
 | 
			
		||||
        //    Method |     Mean |     Error |    StdDev |    StdErr |      Min |       Q1 |   Median |       Q3 |      Max |  Op/s | Scaled |   Gen 0 |  Gen 1 | Allocated |
 | 
			
		||||
        // --------- |---------:|----------:|----------:|----------:|---------:|---------:|---------:|---------:|---------:|------:|-------:|--------:|-------:|----------:|
 | 
			
		||||
        //  Baseline | 2.102 ms | 0.0292 ms | 0.0273 ms | 0.0070 ms | 2.063 ms | 2.080 ms | 2.093 ms | 2.122 ms | 2.152 ms | 475.8 |   1.00 | 31.2500 | 3.9063 |   1.63 KB |
 | 
			
		||||
 | 
			
		||||
        private void GivenOcelotIsRunning(string url)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelot = new WebHostBuilder()
 | 
			
		||||
                .UseKestrel()
 | 
			
		||||
                .UseUrls(url)
 | 
			
		||||
                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
			
		||||
                .ConfigureAppConfiguration((hostingContext, config) =>
 | 
			
		||||
                {
 | 
			
		||||
                    config
 | 
			
		||||
                        .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
 | 
			
		||||
                        .AddJsonFile("appsettings.json", true, true)
 | 
			
		||||
                        .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
 | 
			
		||||
                        .AddJsonFile("ocelot.json")
 | 
			
		||||
                        .AddEnvironmentVariables();
 | 
			
		||||
                })
 | 
			
		||||
                .ConfigureServices(s => {
 | 
			
		||||
                    s.AddOcelot();
 | 
			
		||||
                })
 | 
			
		||||
                .ConfigureLogging((hostingContext, logging) =>
 | 
			
		||||
                {
 | 
			
		||||
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
 | 
			
		||||
                })
 | 
			
		||||
                .UseIISIntegration()
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                })
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            _ocelot.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var configurationPath = Path.Combine(AppContext.BaseDirectory, "ocelot.json");;
 | 
			
		||||
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(configurationPath))
 | 
			
		||||
            {
 | 
			
		||||
                File.Delete(configurationPath);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(configurationPath, jsonConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody)
 | 
			
		||||
        {
 | 
			
		||||
            _service = new WebHostBuilder()
 | 
			
		||||
                .UseUrls(baseUrl)
 | 
			
		||||
                .UseKestrel()
 | 
			
		||||
                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
			
		||||
                .UseIISIntegration()
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UsePathBase(basePath);
 | 
			
		||||
                    app.Run(async context =>
 | 
			
		||||
                    {   
 | 
			
		||||
                        context.Response.StatusCode = statusCode;
 | 
			
		||||
                        await context.Response.WriteAsync(responseBody);
 | 
			
		||||
                    });
 | 
			
		||||
                })
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            _service.Start();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,69 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using BenchmarkDotNet.Attributes;
 | 
			
		||||
using BenchmarkDotNet.Columns;
 | 
			
		||||
using BenchmarkDotNet.Configs;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using BenchmarkDotNet.Attributes.Jobs;
 | 
			
		||||
using Ocelot.Configuration.Repository;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Errors.Middleware;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using BenchmarkDotNet.Diagnosers;
 | 
			
		||||
using BenchmarkDotNet.Validators;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Benchmarks
 | 
			
		||||
{
 | 
			
		||||
    [SimpleJob(launchCount: 1, warmupCount: 2, targetCount: 5)]
 | 
			
		||||
    [Config(typeof(ExceptionHandlerMiddlewareBenchmarks))]
 | 
			
		||||
    public class ExceptionHandlerMiddlewareBenchmarks : ManualConfig
 | 
			
		||||
    {
 | 
			
		||||
        private ExceptionHandlerMiddleware _middleware;
 | 
			
		||||
        private DownstreamContext _downstreamContext;
 | 
			
		||||
        private OcelotRequestDelegate _next;
 | 
			
		||||
 | 
			
		||||
        public ExceptionHandlerMiddlewareBenchmarks()
 | 
			
		||||
        {
 | 
			
		||||
            Add(StatisticColumn.AllStatistics);
 | 
			
		||||
            Add(MemoryDiagnoser.Default);
 | 
			
		||||
            Add(BaselineValidator.FailOnError);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [GlobalSetup]
 | 
			
		||||
        public void SetUp()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceCollection = new ServiceCollection();
 | 
			
		||||
            var config = new ConfigurationRoot(new List<IConfigurationProvider>());
 | 
			
		||||
            var builder = new OcelotBuilder(serviceCollection, config);
 | 
			
		||||
            var services = serviceCollection.BuildServiceProvider();
 | 
			
		||||
            var loggerFactory = services.GetService<IOcelotLoggerFactory>();
 | 
			
		||||
            var configRepo = services.GetService<IInternalConfigurationRepository>();
 | 
			
		||||
            var repo = services.GetService<IRequestScopedDataRepository>();
 | 
			
		||||
            _next = async context => {
 | 
			
		||||
                await Task.CompletedTask;
 | 
			
		||||
                throw new Exception("BOOM");
 | 
			
		||||
            };
 | 
			
		||||
            _middleware = new ExceptionHandlerMiddleware(_next, loggerFactory, configRepo, repo);
 | 
			
		||||
            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Benchmark(Baseline = true)]
 | 
			
		||||
        public async Task Baseline()
 | 
			
		||||
        {
 | 
			
		||||
            await _middleware.Invoke(_downstreamContext);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,9 @@ namespace Ocelot.Benchmarks
 | 
			
		||||
        public static void Main(string[] args)
 | 
			
		||||
        {
 | 
			
		||||
            var switcher = new BenchmarkSwitcher(new[] {
 | 
			
		||||
                   typeof(UrlPathToUrlPathTemplateMatcherBenchmarks),
 | 
			
		||||
                    typeof(UrlPathToUrlPathTemplateMatcherBenchmarks),
 | 
			
		||||
                    typeof(AllTheThingsBenchmarks),
 | 
			
		||||
                    typeof(ExceptionHandlerMiddlewareBenchmarks)
 | 
			
		||||
               });
 | 
			
		||||
 | 
			
		||||
            switcher.Run(args);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
using System;
 | 
			
		||||
using BenchmarkDotNet.Attributes;
 | 
			
		||||
using BenchmarkDotNet.Columns;
 | 
			
		||||
using BenchmarkDotNet.Configs;
 | 
			
		||||
using BenchmarkDotNet.Diagnosers;
 | 
			
		||||
using BenchmarkDotNet.Validators;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Benchmarks
 | 
			
		||||
@@ -15,6 +18,8 @@ namespace Ocelot.Benchmarks
 | 
			
		||||
        public UrlPathToUrlPathTemplateMatcherBenchmarks()
 | 
			
		||||
        {
 | 
			
		||||
            Add(StatisticColumn.AllStatistics);
 | 
			
		||||
            Add(MemoryDiagnoser.Default);
 | 
			
		||||
            Add(BaselineValidator.FailOnError);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [GlobalSetup]
 | 
			
		||||
@@ -25,16 +30,23 @@ namespace Ocelot.Benchmarks
 | 
			
		||||
            _downstreamUrlPathTemplate = "api/product/products/{productId}/variants/";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Benchmark]
 | 
			
		||||
        public void Benchmark1()
 | 
			
		||||
        [Benchmark(Baseline = true)]
 | 
			
		||||
        public void Baseline()
 | 
			
		||||
        {
 | 
			
		||||
            _urlPathMatcher.Match(_downstreamUrlPath, _downstreamUrlPathTemplate);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Benchmark]
 | 
			
		||||
        public void Benchmark2()
 | 
			
		||||
        {
 | 
			
		||||
            _urlPathMatcher.Match(_downstreamUrlPath, _downstreamUrlPathTemplate);
 | 
			
		||||
        }
 | 
			
		||||
        // * Summary *
 | 
			
		||||
 | 
			
		||||
        // BenchmarkDotNet=v0.10.13, OS=macOS 10.12.6 (16G1212) [Darwin 16.7.0]
 | 
			
		||||
        // Intel Core i5-4278U CPU 2.60GHz (Haswell), 1 CPU, 4 logical cores and 2 physical cores
 | 
			
		||||
        // .NET Core SDK=2.1.4
 | 
			
		||||
        //   [Host]     : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
 | 
			
		||||
        //   DefaultJob : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //      Method |     Mean |     Error |    StdDev |    StdErr |      Min |       Q1 |   Median |       Q3 |      Max |      Op/s |
 | 
			
		||||
        // ----------- |---------:|----------:|----------:|----------:|---------:|---------:|---------:|---------:|---------:|----------:|
 | 
			
		||||
        //  Benchmark1 | 3.133 us | 0.0492 us | 0.0460 us | 0.0119 us | 3.082 us | 3.100 us | 3.122 us | 3.168 us | 3.233 us | 319,161.9 |
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,137 @@
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using Ocelot.Configuration.Repository;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Infrastructure.Consul;
 | 
			
		||||
    using Ocelot.Logging;
 | 
			
		||||
    using Ocelot.Configuration.File;
 | 
			
		||||
    using Ocelot.Cache;
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using Ocelot.Responses;
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Configuration.Builder;
 | 
			
		||||
    using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
    using Consul;
 | 
			
		||||
    using Newtonsoft.Json;
 | 
			
		||||
    using System.Text;
 | 
			
		||||
    using System.Threading;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
 | 
			
		||||
    public class ConsulFileConfigurationRepositoryTests
 | 
			
		||||
    {
 | 
			
		||||
        private ConsulFileConfigurationRepository _repo;
 | 
			
		||||
        private Mock<IOcelotCache<FileConfiguration>> _cache;
 | 
			
		||||
        private Mock<IInternalConfigurationRepository> _internalRepo;
 | 
			
		||||
        private Mock<IConsulClientFactory> _factory;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private Mock<IConsulClient> _client;
 | 
			
		||||
        private Mock<IKVEndpoint> _kvEndpoint;
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
        private Response _result;
 | 
			
		||||
 | 
			
		||||
        public ConsulFileConfigurationRepositoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _cache = new Mock<IOcelotCache<FileConfiguration>>();
 | 
			
		||||
            _internalRepo = new Mock<IInternalConfigurationRepository>();
 | 
			
		||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
 | 
			
		||||
            _factory = new Mock<IConsulClientFactory>();
 | 
			
		||||
            _client = new Mock<IConsulClient>();
 | 
			
		||||
            _kvEndpoint = new Mock<IKVEndpoint>();
 | 
			
		||||
 | 
			
		||||
            _client
 | 
			
		||||
                .Setup(x => x.KV)
 | 
			
		||||
                .Returns(_kvEndpoint.Object);
 | 
			
		||||
            _factory
 | 
			
		||||
                .Setup(x => x.Get(It.IsAny<ConsulRegistryConfiguration>()))
 | 
			
		||||
                .Returns(_client.Object);
 | 
			
		||||
 | 
			
		||||
            _internalRepo
 | 
			
		||||
                .Setup(x => x.Get())
 | 
			
		||||
                .Returns(new OkResponse<IInternalConfiguration>(new InternalConfiguration(new List<ReRoute>(), "", new ServiceProviderConfigurationBuilder().Build(), "")));
 | 
			
		||||
            
 | 
			
		||||
            _repo = new ConsulFileConfigurationRepository(_cache.Object, _internalRepo.Object, _factory.Object, _loggerFactory.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_config()
 | 
			
		||||
        {
 | 
			
		||||
            var config = FakeFileConfiguration();
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenIHaveAConfiguration(config))
 | 
			
		||||
                .And(_ => GivenWritingToConsulSucceeds())
 | 
			
		||||
                .When(_ => WhenISetTheConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigurationIsStoredAs(config))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenWritingToConsulSucceeds()
 | 
			
		||||
        {
 | 
			
		||||
            var response = new WriteResult<bool>();
 | 
			
		||||
            response.Response = true;
 | 
			
		||||
 | 
			
		||||
            _kvEndpoint
 | 
			
		||||
                .Setup(x => x.Put(It.IsAny<KVPair>(), It.IsAny<CancellationToken>())).ReturnsAsync(response);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheConfigurationIsStoredAs(FileConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            var json = JsonConvert.SerializeObject(config, Formatting.Indented);
 | 
			
		||||
 | 
			
		||||
            var bytes = Encoding.UTF8.GetBytes(json);
 | 
			
		||||
 | 
			
		||||
            _kvEndpoint
 | 
			
		||||
                .Verify(x => x.Put(It.Is<KVPair>(k => k.Value.SequenceEqual(bytes)), It.IsAny<CancellationToken>()), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task WhenISetTheConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            _result = await _repo.Set(_fileConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAConfiguration(FileConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            _fileConfiguration = config;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private FileConfiguration FakeFileConfiguration()
 | 
			
		||||
        {
 | 
			
		||||
            var reRoutes = new List<FileReRoute>
 | 
			
		||||
            {
 | 
			
		||||
                new FileReRoute
 | 
			
		||||
                {
 | 
			
		||||
                    DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileHostAndPort
 | 
			
		||||
                        {
 | 
			
		||||
                            Host = "123.12.12.12",
 | 
			
		||||
                            Port = 80,
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    DownstreamScheme = "https",
 | 
			
		||||
                    DownstreamPathTemplate = "/asdfs/test/{test}"
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            var globalConfiguration = new FileGlobalConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
 | 
			
		||||
                {
 | 
			
		||||
                    Port = 198,
 | 
			
		||||
                    Host = "blah"
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            return new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                GlobalConfiguration = globalConfiguration,
 | 
			
		||||
                ReRoutes = reRoutes
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +1,22 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Ocelot.Configuration.Repository;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class FileConfigurationRepositoryTests
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration.File;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using Newtonsoft.Json;
 | 
			
		||||
    using System.IO;
 | 
			
		||||
    using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
    using Ocelot.Configuration.Repository;
 | 
			
		||||
 | 
			
		||||
    public class DiskFileConfigurationRepositoryTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Mock<IHostingEnvironment> _hostingEnvironment = new Mock<IHostingEnvironment>();
 | 
			
		||||
        private IFileConfigurationRepository _repo;
 | 
			
		||||
        private string _configurationPath;
 | 
			
		||||
        private FileConfiguration _result;
 | 
			
		||||
        private FileConfiguration _fileConfiguration;
 | 
			
		||||
 | 
			
		||||
@@ -24,7 +25,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        // tests but whatever...
 | 
			
		||||
        private string _environmentName = "DEV.DEV";
 | 
			
		||||
 | 
			
		||||
        public FileConfigurationRepositoryTests()
 | 
			
		||||
        public DiskFileConfigurationRepositoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName);
 | 
			
		||||
            _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object);
 | 
			
		||||
@@ -35,9 +36,9 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            var config = FakeFileConfigurationForGet();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(x => x.WhenIGetTheReRoutes())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned(config))
 | 
			
		||||
            this.Given(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(_ => WhenIGetTheReRoutes())
 | 
			
		||||
                .Then(_ => ThenTheFollowingIsReturned(config))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -46,10 +47,10 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            var config = FakeFileConfigurationForGet();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheEnvironmentNameIsUnavailable())
 | 
			
		||||
                .And(x => x.GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(x => x.WhenIGetTheReRoutes())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned(config))
 | 
			
		||||
            this.Given(_ => GivenTheEnvironmentNameIsUnavailable())
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(_ => WhenIGetTheReRoutes())
 | 
			
		||||
                .Then(_ => ThenTheFollowingIsReturned(config))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -58,9 +59,10 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            var config = FakeFileConfigurationForSet();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenIHaveAConfiguration(config))
 | 
			
		||||
                .When(x => WhenISetTheConfiguration())
 | 
			
		||||
                .Then(x => ThenTheConfigurationIsStoredAs(config))
 | 
			
		||||
            this.Given(_ => GivenIHaveAConfiguration(config))
 | 
			
		||||
                .When(_ => WhenISetTheConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigurationIsStoredAs(config))
 | 
			
		||||
                .And(_ => ThenTheConfigurationJsonIsIndented(config))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -68,10 +70,12 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        public void should_set_file_configuration_if_environment_name_is_unavailable()
 | 
			
		||||
        {
 | 
			
		||||
            var config = FakeFileConfigurationForSet();
 | 
			
		||||
            this.Given(x => GivenIHaveAConfiguration(config))
 | 
			
		||||
                .And(x => GivenTheEnvironmentNameIsUnavailable())
 | 
			
		||||
                .When(x => WhenISetTheConfiguration())
 | 
			
		||||
                .Then(x => ThenTheConfigurationIsStoredAs(config))
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenIHaveAConfiguration(config))
 | 
			
		||||
                .And(_ => GivenTheEnvironmentNameIsUnavailable())
 | 
			
		||||
                .When(_ => WhenISetTheConfiguration())
 | 
			
		||||
                .Then(_ => ThenTheConfigurationIsStoredAs(config))
 | 
			
		||||
                .And(_ => ThenTheConfigurationJsonIsIndented(config))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -117,16 +121,25 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigurationIs(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var configurationPath = $"{AppContext.BaseDirectory}/ocelot{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json";
 | 
			
		||||
            _configurationPath = $"{AppContext.BaseDirectory}/ocelot{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json";
 | 
			
		||||
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration, Formatting.Indented);
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(configurationPath))
 | 
			
		||||
            if (File.Exists(_configurationPath))
 | 
			
		||||
            {
 | 
			
		||||
                File.Delete(configurationPath);
 | 
			
		||||
                File.Delete(_configurationPath);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(configurationPath, jsonConfiguration);
 | 
			
		||||
            File.WriteAllText(_configurationPath, jsonConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheConfigurationJsonIsIndented(FileConfiguration expecteds)
 | 
			
		||||
        {
 | 
			
		||||
            var path = !string.IsNullOrEmpty(_configurationPath) ? _configurationPath : _configurationPath = $"{AppContext.BaseDirectory}/ocelot{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json";
 | 
			
		||||
            
 | 
			
		||||
            var resultText = File.ReadAllText(_configurationPath);
 | 
			
		||||
            var expectedText = JsonConvert.SerializeObject(expecteds, Formatting.Indented);
 | 
			
		||||
            resultText.ShouldBe(expectedText);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheReRoutes()
 | 
			
		||||
		Reference in New Issue
	
	Block a user