mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 15:30:49 +08:00 
			
		
		
		
	Feature/#295 consul acl (#307)
* removed file * updated package * updated package * updated package * updated package * updated package * updated package * updated package * all packages updated * #295 can add token to service provider config and this will be used by consul clients to get services and configuration * #295 wait longer for this test
This commit is contained in:
		@@ -38,3 +38,18 @@ and LeastConnection algorithm you can use. If no load balancer is specified Ocel
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
When this is set up Ocelot will lookup the downstream host and port from the service discover provider and load balance requests across any available services.
 | 
			
		||||
 | 
			
		||||
ACL Token
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
If you are using ACL with Consul Ocelot supports adding the X-Consul-Token header. In order so this to work you must add the additional property below.
 | 
			
		||||
 | 
			
		||||
.. code-block:: json
 | 
			
		||||
 | 
			
		||||
    "ServiceDiscoveryProvider": {
 | 
			
		||||
        "Host": "localhost",
 | 
			
		||||
        "Port": 9500,
 | 
			
		||||
        "Token": "footoken"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
Ocelot will add this token to the consul client that it uses to make requests and that is then used for every request.
 | 
			
		||||
@@ -5,28 +5,35 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
        private string _serviceDiscoveryProviderHost;
 | 
			
		||||
        private int _serviceDiscoveryProviderPort;
 | 
			
		||||
        private string _type;
 | 
			
		||||
        private string _token;
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost)
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost)
 | 
			
		||||
        {
 | 
			
		||||
            _serviceDiscoveryProviderHost = serviceDiscoveryProviderHost;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderPort(int serviceDiscoveryProviderPort)
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithPort(int serviceDiscoveryProviderPort)
 | 
			
		||||
        {
 | 
			
		||||
            _serviceDiscoveryProviderPort = serviceDiscoveryProviderPort;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderType(string type)
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithType(string type)
 | 
			
		||||
        {
 | 
			
		||||
            _type = type;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderConfigurationBuilder WithToken(string token)
 | 
			
		||||
        {
 | 
			
		||||
            _token = token;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderConfiguration Build()
 | 
			
		||||
        {
 | 
			
		||||
            return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort);
 | 
			
		||||
            return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,10 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
            var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
 | 
			
		||||
 | 
			
		||||
            return new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(serviceProviderPort)
 | 
			
		||||
                .WithServiceDiscoveryProviderType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
 | 
			
		||||
                .WithHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
 | 
			
		||||
                .WithPort(serviceProviderPort)
 | 
			
		||||
                .WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
 | 
			
		||||
                .WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
 | 
			
		||||
                .Build();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,5 +5,6 @@ namespace Ocelot.Configuration.File
 | 
			
		||||
        public string Host {get;set;}
 | 
			
		||||
        public int Port { get; set; }
 | 
			
		||||
        public string Type { get; set; }
 | 
			
		||||
        public string Token { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@ using System.Threading.Tasks;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Infrastructure.Consul;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.ServiceDiscovery;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Repository
 | 
			
		||||
@@ -13,31 +13,31 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
    public class ConsulFileConfigurationRepository : IFileConfigurationRepository
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConsulClient _consul;
 | 
			
		||||
        private string _ocelotConfiguration = "OcelotConfiguration";
 | 
			
		||||
        private const string OcelotConfiguration = "OcelotConfiguration";
 | 
			
		||||
        private readonly Cache.IOcelotCache<FileConfiguration> _cache;
 | 
			
		||||
 | 
			
		||||
        public ConsulFileConfigurationRepository(Cache.IOcelotCache<FileConfiguration> cache, ServiceProviderConfiguration serviceProviderConfig)
 | 
			
		||||
        public ConsulFileConfigurationRepository(
 | 
			
		||||
            Cache.IOcelotCache<FileConfiguration> cache, 
 | 
			
		||||
            ServiceProviderConfiguration serviceProviderConfig, 
 | 
			
		||||
            IConsulClientFactory factory)
 | 
			
		||||
        {
 | 
			
		||||
            var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host;
 | 
			
		||||
            var consulPort = serviceProviderConfig?.Port ?? 8500;
 | 
			
		||||
            var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration);
 | 
			
		||||
            var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, serviceProviderConfig?.Token);
 | 
			
		||||
            _cache = cache;
 | 
			
		||||
            _consul = new ConsulClient(c =>
 | 
			
		||||
            {
 | 
			
		||||
                c.Address = new Uri($"http://{configuration.HostName}:{configuration.Port}");
 | 
			
		||||
            });
 | 
			
		||||
            _consul = factory.Get(config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<Response<FileConfiguration>> Get()
 | 
			
		||||
        {
 | 
			
		||||
            var config = _cache.Get(_ocelotConfiguration, _ocelotConfiguration);
 | 
			
		||||
            var config = _cache.Get(OcelotConfiguration, OcelotConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (config != null)
 | 
			
		||||
            {
 | 
			
		||||
                return new OkResponse<FileConfiguration>(config);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var queryResult = await _consul.KV.Get(_ocelotConfiguration);
 | 
			
		||||
            var queryResult = await _consul.KV.Get(OcelotConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (queryResult.Response == null)
 | 
			
		||||
            {
 | 
			
		||||
@@ -59,7 +59,7 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
 | 
			
		||||
            var bytes = Encoding.UTF8.GetBytes(json);
 | 
			
		||||
 | 
			
		||||
            var kvPair = new KVPair(_ocelotConfiguration)
 | 
			
		||||
            var kvPair = new KVPair(OcelotConfiguration)
 | 
			
		||||
            {
 | 
			
		||||
                Value = bytes
 | 
			
		||||
            };
 | 
			
		||||
@@ -68,7 +68,7 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
 | 
			
		||||
            if (result.Response)
 | 
			
		||||
            {
 | 
			
		||||
                _cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), _ocelotConfiguration);
 | 
			
		||||
                _cache.AddAndDelete(OcelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), OcelotConfiguration);
 | 
			
		||||
 | 
			
		||||
                return new OkResponse();
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,15 +2,17 @@
 | 
			
		||||
{
 | 
			
		||||
    public class ServiceProviderConfiguration
 | 
			
		||||
    {
 | 
			
		||||
        public ServiceProviderConfiguration(string type, string host, int port)
 | 
			
		||||
        public ServiceProviderConfiguration(string type, string host, int port, string token)
 | 
			
		||||
        {
 | 
			
		||||
            Host = host;
 | 
			
		||||
            Port = port;
 | 
			
		||||
            Token = token;
 | 
			
		||||
            Type = type;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string Host { get; private set; }
 | 
			
		||||
        public int Port { get; private set; }
 | 
			
		||||
        public string Type { get; private set; }
 | 
			
		||||
        public string Host { get; }
 | 
			
		||||
        public int Port { get; }
 | 
			
		||||
        public string Type { get; }
 | 
			
		||||
        public string Token { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,7 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
    using System.Net.Http;
 | 
			
		||||
    using Butterfly.Client.AspNetCore;
 | 
			
		||||
    using Ocelot.Infrastructure;
 | 
			
		||||
    using Ocelot.Infrastructure.Consul;
 | 
			
		||||
 | 
			
		||||
    public class OcelotBuilder : IOcelotBuilder
 | 
			
		||||
    {
 | 
			
		||||
@@ -152,6 +153,7 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            _services.TryAddSingleton<IConsulPollerConfiguration, InMemoryConsulPollerConfiguration>();
 | 
			
		||||
            _services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>();
 | 
			
		||||
            _services.TryAddSingleton<IPlaceholders, Placeholders>();
 | 
			
		||||
            _services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
 | 
			
		||||
@@ -236,10 +238,12 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
        {
 | 
			
		||||
            var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0);
 | 
			
		||||
            var serviceDiscoveryHost = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty);
 | 
			
		||||
            var serviceDiscoveryToken = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Token", string.Empty);
 | 
			
		||||
 | 
			
		||||
            var config = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(serviceDiscoveryPort)
 | 
			
		||||
                .WithServiceDiscoveryProviderHost(serviceDiscoveryHost)
 | 
			
		||||
                .WithPort(serviceDiscoveryPort)
 | 
			
		||||
                .WithHost(serviceDiscoveryHost)
 | 
			
		||||
                .WithToken(serviceDiscoveryToken)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            _services.AddSingleton<ServiceProviderConfiguration>(config);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								src/Ocelot/Infrastructure/Consul/ConsulClientFactory.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Ocelot/Infrastructure/Consul/ConsulClientFactory.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Infrastructure.Consul
 | 
			
		||||
{
 | 
			
		||||
    public class ConsulClientFactory : IConsulClientFactory
 | 
			
		||||
    {
 | 
			
		||||
        public ConsulClient Get(ConsulRegistryConfiguration config)
 | 
			
		||||
        {
 | 
			
		||||
            return new ConsulClient(c =>
 | 
			
		||||
            {
 | 
			
		||||
                c.Address = new Uri($"http://{config.Host}:{config.Port}");
 | 
			
		||||
 | 
			
		||||
                if (!string.IsNullOrEmpty(config?.Token))
 | 
			
		||||
                {
 | 
			
		||||
                    c.Token = config.Token;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/Ocelot/Infrastructure/Consul/IConsulClientFactory.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/Ocelot/Infrastructure/Consul/IConsulClientFactory.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
using Consul;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Infrastructure.Consul
 | 
			
		||||
{
 | 
			
		||||
    public interface IConsulClientFactory
 | 
			
		||||
    {
 | 
			
		||||
        ConsulClient Get(ConsulRegistryConfiguration config);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,27 +26,27 @@
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
     <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> 
 | 
			
		||||
    <PackageReference Include="FluentValidation" Version="7.2.1" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="FluentValidation" Version="7.5.2" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.4.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
    <PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Core" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.3" />
 | 
			
		||||
    <PackageReference Include="Polly" Version="5.3.1" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4" Version="2.0.2" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Core" Version="1.1.2" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.2" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.2" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.4" />
 | 
			
		||||
    <PackageReference Include="Polly" Version="5.8.0" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4" Version="2.1.3" />
 | 
			
		||||
    <PackageReference Include="Rafty" Version="0.4.2" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,15 +2,17 @@ namespace Ocelot.ServiceDiscovery.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class ConsulRegistryConfiguration
 | 
			
		||||
    {
 | 
			
		||||
        public ConsulRegistryConfiguration(string hostName, int port, string keyOfServiceInConsul)
 | 
			
		||||
        public ConsulRegistryConfiguration(string host, int port, string keyOfServiceInConsul, string token)
 | 
			
		||||
        {
 | 
			
		||||
            HostName = hostName;
 | 
			
		||||
            Host = host;
 | 
			
		||||
            Port = port;
 | 
			
		||||
            KeyOfServiceInConsul = keyOfServiceInConsul;
 | 
			
		||||
            Token = token;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string KeyOfServiceInConsul { get; private set; }
 | 
			
		||||
        public string HostName { get; private set; }
 | 
			
		||||
        public int Port { get; private set; }
 | 
			
		||||
        public string KeyOfServiceInConsul { get; }
 | 
			
		||||
        public string Host { get; }
 | 
			
		||||
        public int Port { get; }
 | 
			
		||||
        public string Token { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Ocelot.Infrastructure.Consul;
 | 
			
		||||
using Ocelot.Infrastructure.Extensions;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
@@ -12,30 +13,27 @@ namespace Ocelot.ServiceDiscovery.Providers
 | 
			
		||||
{
 | 
			
		||||
    public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConsulRegistryConfiguration _consulConfig;
 | 
			
		||||
        private readonly ConsulRegistryConfiguration _config;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly ConsulClient _consul;
 | 
			
		||||
        private const string VersionPrefix = "version-";
 | 
			
		||||
 | 
			
		||||
        public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration consulRegistryConfiguration, IOcelotLoggerFactory factory)
 | 
			
		||||
        public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
 | 
			
		||||
        {;
 | 
			
		||||
            _logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
 | 
			
		||||
 | 
			
		||||
            var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName;
 | 
			
		||||
            var consulHost = string.IsNullOrEmpty(config?.Host) ? "localhost" : config.Host;
 | 
			
		||||
 | 
			
		||||
            var consulPort = consulRegistryConfiguration?.Port ?? 8500;
 | 
			
		||||
            var consulPort = config?.Port ?? 8500;
 | 
			
		||||
 | 
			
		||||
            _consulConfig = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.KeyOfServiceInConsul);
 | 
			
		||||
            _config = new ConsulRegistryConfiguration(consulHost, consulPort, config?.KeyOfServiceInConsul, config?.Token);
 | 
			
		||||
 | 
			
		||||
            _consul = new ConsulClient(config =>
 | 
			
		||||
            {
 | 
			
		||||
                config.Address = new Uri($"http://{_consulConfig.HostName}:{_consulConfig.Port}");
 | 
			
		||||
            });
 | 
			
		||||
            _consul = clientFactory.Get(_config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<List<Service>> Get()
 | 
			
		||||
        {
 | 
			
		||||
            var queryResult = await _consul.Health.Service(_consulConfig.KeyOfServiceInConsul, string.Empty, true);
 | 
			
		||||
            var queryResult = await _consul.Health.Service(_config.KeyOfServiceInConsul, string.Empty, true);
 | 
			
		||||
 | 
			
		||||
            var services = new List<Service>();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Infrastructure.Consul;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Providers;
 | 
			
		||||
@@ -10,10 +11,12 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
    public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IOcelotLoggerFactory _factory;
 | 
			
		||||
        private readonly IConsulClientFactory _clientFactory;
 | 
			
		||||
 | 
			
		||||
        public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory)
 | 
			
		||||
        public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
 | 
			
		||||
        {
 | 
			
		||||
            _factory = factory;
 | 
			
		||||
            _clientFactory = clientFactory;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
 | 
			
		||||
@@ -43,8 +46,8 @@ namespace Ocelot.ServiceDiscovery
 | 
			
		||||
                return new ServiceFabricServiceDiscoveryProvider(config);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName);
 | 
			
		||||
            return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory);
 | 
			
		||||
            var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName, serviceConfig.Token);
 | 
			
		||||
            return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory, _clientFactory);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                 .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
 | 
			
		||||
            var commandOnAllStateMachines = WaitFor(5000).Until(() => _butterflyCalled == 4);
 | 
			
		||||
            var commandOnAllStateMachines = WaitFor(10000).Until(() => _butterflyCalled == 4);
 | 
			
		||||
 | 
			
		||||
            commandOnAllStateMachines.ShouldBeTrue();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
    public class HeaderTests : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private IWebHost _builder;
 | 
			
		||||
        private string _cookieValue;
 | 
			
		||||
        private int _count;
 | 
			
		||||
        private readonly Steps _steps;
 | 
			
		||||
 | 
			
		||||
@@ -278,26 +277,27 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UsePathBase(basePath);
 | 
			
		||||
                    app.Run(async context =>
 | 
			
		||||
                    {   
 | 
			
		||||
                        if(_count == 0)
 | 
			
		||||
                    app.Run(context =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (_count == 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            context.Response.Cookies.Append("test", "0");
 | 
			
		||||
                            _count++;
 | 
			
		||||
                            context.Response.StatusCode = statusCode;
 | 
			
		||||
                            return;
 | 
			
		||||
                        } 
 | 
			
		||||
                            return Task.CompletedTask;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if(context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
 | 
			
		||||
                        if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
 | 
			
		||||
                        {
 | 
			
		||||
                            if(cookieValue == "0" || headerValue == "test=1; path=/")
 | 
			
		||||
                            if (cookieValue == "0" || headerValue == "test=1; path=/")
 | 
			
		||||
                            {
 | 
			
		||||
                                context.Response.StatusCode = statusCode;
 | 
			
		||||
                                return;
 | 
			
		||||
                                return Task.CompletedTask;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        context.Response.StatusCode = 500;
 | 
			
		||||
                        return Task.CompletedTask;
 | 
			
		||||
                    });
 | 
			
		||||
                })
 | 
			
		||||
                .Build();
 | 
			
		||||
 
 | 
			
		||||
@@ -27,26 +27,26 @@
 | 
			
		||||
    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="CacheManager.Serialization.Json" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Serialization.Json" Version="1.1.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
 | 
			
		||||
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
 | 
			
		||||
    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
			
		||||
    <PackageReference Include="Shouldly" Version="3.0.0" />
 | 
			
		||||
    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.3" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.4" />
 | 
			
		||||
    <PackageReference Include="xunit" Version="2.3.1" />
 | 
			
		||||
     <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> 
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
@@ -22,9 +23,10 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
        private readonly List<ServiceEntry> _serviceEntries;
 | 
			
		||||
        private int _counterOne;
 | 
			
		||||
        private int _counterTwo;
 | 
			
		||||
        private static readonly object _syncLock = new object();
 | 
			
		||||
        private static readonly object SyncLock = new object();
 | 
			
		||||
        private IWebHost _builder;
 | 
			
		||||
        private string _downstreamPath;
 | 
			
		||||
        private string _receivedToken;
 | 
			
		||||
 | 
			
		||||
        public ServiceDiscoveryTests()
 | 
			
		||||
        {
 | 
			
		||||
@@ -100,13 +102,13 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //test from issue 213
 | 
			
		||||
        //test from issue #213
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_handle_request_to_consul_for_downstream_service_and_make_request()
 | 
			
		||||
        {
 | 
			
		||||
            var consulPort = 8505;
 | 
			
		||||
            var serviceName = "web";
 | 
			
		||||
            var downstreamServiceOneUrl = "http://localhost:8080";
 | 
			
		||||
            const int consulPort = 8505;
 | 
			
		||||
            const string serviceName = "web";
 | 
			
		||||
            const string downstreamServiceOneUrl = "http://localhost:8080";
 | 
			
		||||
            var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
 | 
			
		||||
            var serviceEntryOne = new ServiceEntry()
 | 
			
		||||
            {
 | 
			
		||||
@@ -116,7 +118,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                    Address = "localhost",
 | 
			
		||||
                    Port = 8080,
 | 
			
		||||
                    ID = "web_90_0_2_224_8080",
 | 
			
		||||
                    Tags = new string[1]{"version-v1"}
 | 
			
		||||
                    Tags = new[] {"version-v1"}
 | 
			
		||||
                },
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -145,14 +147,73 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                    }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
                this.Given(x => x.GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/api/home", 200, "Hello from Laura"))                
 | 
			
		||||
                .And(x => x.GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
 | 
			
		||||
                .And(x => x.GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
 | 
			
		||||
                .And(x => _steps.GivenThereIsAConfiguration(configuration))
 | 
			
		||||
                .And(x => _steps.GivenOcelotIsRunning())
 | 
			
		||||
                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/home"))
 | 
			
		||||
                .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
			
		||||
                .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
 | 
			
		||||
            this.Given(x => x.GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/api/home", 200, "Hello from Laura"))                
 | 
			
		||||
            .And(x => x.GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
 | 
			
		||||
            .And(x => x.GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
 | 
			
		||||
            .And(x => _steps.GivenThereIsAConfiguration(configuration))
 | 
			
		||||
            .And(x => _steps.GivenOcelotIsRunning())
 | 
			
		||||
                .When(x => _steps.WhenIGetUrlOnTheApiGateway("/home"))
 | 
			
		||||
            .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
			
		||||
            .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
 | 
			
		||||
            .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //test from issue #295
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_token_to_make_request_to_consul()
 | 
			
		||||
        {
 | 
			
		||||
            var token = "abctoken";
 | 
			
		||||
            var consulPort = 8515;
 | 
			
		||||
            var serviceName = "web";
 | 
			
		||||
            var downstreamServiceOneUrl = "http://localhost:8081";
 | 
			
		||||
            var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
 | 
			
		||||
            var serviceEntryOne = new ServiceEntry()
 | 
			
		||||
            {
 | 
			
		||||
                Service = new AgentService()
 | 
			
		||||
                {
 | 
			
		||||
                    Service = serviceName,
 | 
			
		||||
                    Address = "localhost",
 | 
			
		||||
                    Port = 8081,
 | 
			
		||||
                    ID = "web_90_0_2_224_8080",
 | 
			
		||||
                    Tags = new[] { "version-v1" }
 | 
			
		||||
                },
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            var configuration = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ReRoutes = new List<FileReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileReRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamPathTemplate = "/api/home",
 | 
			
		||||
                            DownstreamScheme = "http",
 | 
			
		||||
                            UpstreamPathTemplate = "/home",
 | 
			
		||||
                            UpstreamHttpMethod = new List<string> { "Get", "Options" },
 | 
			
		||||
                            ServiceName = serviceName,
 | 
			
		||||
                            LoadBalancer = "LeastConnection",
 | 
			
		||||
                            UseServiceDiscovery = true,
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                GlobalConfiguration = new FileGlobalConfiguration()
 | 
			
		||||
                {
 | 
			
		||||
                    ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
 | 
			
		||||
                    {
 | 
			
		||||
                        Host = "localhost",
 | 
			
		||||
                        Port = consulPort,
 | 
			
		||||
                        Token = token
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/api/home", 200, "Hello from Laura"))
 | 
			
		||||
                .And(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
 | 
			
		||||
                .And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
 | 
			
		||||
                .And(_ => _steps.GivenThereIsAConfiguration(configuration))
 | 
			
		||||
                .And(_ => _steps.GivenOcelotIsRunning())
 | 
			
		||||
                .When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home"))
 | 
			
		||||
                .Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
			
		||||
                .And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
 | 
			
		||||
                .And(_ => _receivedToken.ShouldBe(token))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -289,6 +350,11 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                                {
 | 
			
		||||
                                    if(context.Request.Path.Value == $"/v1/health/service/{serviceName}")
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
 | 
			
		||||
                                        {
 | 
			
		||||
                                            _receivedToken = values.First();
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                        await context.Response.WriteJsonAsync(_serviceEntries);
 | 
			
		||||
                                    }
 | 
			
		||||
                                });
 | 
			
		||||
@@ -312,8 +378,8 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var response = string.Empty;
 | 
			
		||||
                            lock (_syncLock)
 | 
			
		||||
                            string response;
 | 
			
		||||
                            lock (SyncLock)
 | 
			
		||||
                            {
 | 
			
		||||
                                _counterOne++;
 | 
			
		||||
                                response = _counterOne.ToString();
 | 
			
		||||
@@ -321,7 +387,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                            context.Response.StatusCode = statusCode;
 | 
			
		||||
                            await context.Response.WriteAsync(response);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (System.Exception exception)
 | 
			
		||||
                        catch (Exception exception)
 | 
			
		||||
                        {
 | 
			
		||||
                            await context.Response.WriteAsync(exception.StackTrace);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -346,8 +412,8 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var response = string.Empty;
 | 
			
		||||
                            lock (_syncLock)
 | 
			
		||||
                            string response;
 | 
			
		||||
                            lock (SyncLock)
 | 
			
		||||
                            {
 | 
			
		||||
                                _counterTwo++;
 | 
			
		||||
                                response = _counterTwo.ToString();
 | 
			
		||||
@@ -356,7 +422,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                            context.Response.StatusCode = statusCode;
 | 
			
		||||
                            await context.Response.WriteAsync(response);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (System.Exception exception)
 | 
			
		||||
                        catch (Exception exception)
 | 
			
		||||
                        {
 | 
			
		||||
                            await context.Response.WriteAsync(exception.StackTrace);
 | 
			
		||||
                        }                  
 | 
			
		||||
 
 | 
			
		||||
@@ -1,722 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using CacheManager.Core;
 | 
			
		||||
using IdentityServer4.AccessTokenValidation;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.TestHost;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
 | 
			
		||||
using Ocelot.AcceptanceTests.Caching;
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
 | 
			
		||||
||||||| merged common ancestors
 | 
			
		||||
=======
 | 
			
		||||
using System.IO.Compression;
 | 
			
		||||
using System.Text;
 | 
			
		||||
>>>>>>> develop
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.AcceptanceTests
 | 
			
		||||
{
 | 
			
		||||
    public class Steps : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private TestServer _ocelotServer;
 | 
			
		||||
        private HttpClient _ocelotClient;
 | 
			
		||||
        private HttpResponseMessage _response;
 | 
			
		||||
        private HttpContent _postContent;
 | 
			
		||||
        private BearerToken _token;
 | 
			
		||||
        public HttpClient OcelotClient => _ocelotClient;
 | 
			
		||||
        public string RequestIdKey = "OcRequestId";
 | 
			
		||||
        private readonly Random _random;
 | 
			
		||||
        private IWebHostBuilder _webHostBuilder;
 | 
			
		||||
 | 
			
		||||
        public Steps()
 | 
			
		||||
        {
 | 
			
		||||
            _random = new Random();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var configurationPath = TestConfiguration.ConfigurationPath;
 | 
			
		||||
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(configurationPath))
 | 
			
		||||
            {
 | 
			
		||||
                File.Delete(configurationPath);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(configurationPath, jsonConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration, string configurationPath)
 | 
			
		||||
        {
 | 
			
		||||
            var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(configurationPath))
 | 
			
		||||
            {
 | 
			
		||||
                File.Delete(configurationPath);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(configurationPath, jsonConfiguration);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void GivenOcelotIsRunning()
 | 
			
		||||
        {
 | 
			
		||||
            _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();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _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)
 | 
			
		||||
        {
 | 
			
		||||
            _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();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseMiddleware<T>(callback);
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne, TWo>() 
 | 
			
		||||
            where TOne : DelegatingHandler
 | 
			
		||||
            where TWo : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
            _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.AddSingleton(_webHostBuilder);
 | 
			
		||||
                    s.AddOcelot()
 | 
			
		||||
                        .AddDelegatingHandler<TOne>()
 | 
			
		||||
                        .AddDelegatingHandler<TWo>();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(a =>
 | 
			
		||||
                {
 | 
			
		||||
                    a.UseOcelot().Wait();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne>(FakeDependency dependency) 
 | 
			
		||||
            where TOne : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
            _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.AddSingleton(_webHostBuilder);
 | 
			
		||||
                    s.AddSingleton<FakeDependency>(dependency);
 | 
			
		||||
                    s.AddOcelot()
 | 
			
		||||
                        .AddDelegatingHandler<TOne>();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(a =>
 | 
			
		||||
                {
 | 
			
		||||
                    a.UseOcelot().Wait();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void GivenOcelotIsRunning(Action<IdentityServerAuthenticationOptions> options, string authenticationProviderKey)
 | 
			
		||||
        {
 | 
			
		||||
            _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();
 | 
			
		||||
                    s.AddAuthentication()
 | 
			
		||||
                        .AddIdentityServerAuthentication(authenticationProviderKey, options);
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheResponseHeaderIs(string key, string value)
 | 
			
		||||
        {
 | 
			
		||||
            var header = _response.Headers.GetValues(key);
 | 
			
		||||
            header.First().ShouldBe(value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenOcelotIsRunningUsingJsonSerializedCache()
 | 
			
		||||
        {
 | 
			
		||||
            _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()
 | 
			
		||||
                        .AddCacheManager((x) =>
 | 
			
		||||
                        {
 | 
			
		||||
                            x.WithMicrosoftLogging(log =>
 | 
			
		||||
                                {
 | 
			
		||||
                                    log.AddConsole(LogLevel.Debug);
 | 
			
		||||
                                })
 | 
			
		||||
                                .WithJsonSerializer()
 | 
			
		||||
                                .WithHandle(typeof(InMemoryJsonHandle<>));
 | 
			
		||||
                        });
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                }); 
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenOcelotIsRunningUsingConsulToStoreConfig()
 | 
			
		||||
        {
 | 
			
		||||
            _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().AddStoreOcelotConfigurationInConsul();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache()
 | 
			
		||||
        {
 | 
			
		||||
            _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()
 | 
			
		||||
                        .AddCacheManager((x) =>
 | 
			
		||||
                        {
 | 
			
		||||
                            x.WithMicrosoftLogging(log =>
 | 
			
		||||
                                {
 | 
			
		||||
                                    log.AddConsole(LogLevel.Debug);
 | 
			
		||||
                                })
 | 
			
		||||
                                .WithJsonSerializer()
 | 
			
		||||
                                .WithHandle(typeof(InMemoryJsonHandle<>));
 | 
			
		||||
                        })
 | 
			
		||||
                        .AddStoreOcelotConfigurationInConsul();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.UseOcelot().Wait();
 | 
			
		||||
                }); 
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder);
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void ThenTheResponseShouldBe(FileConfiguration expecteds)
 | 
			
		||||
        {
 | 
			
		||||
            var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
 | 
			
		||||
 | 
			
		||||
            response.GlobalConfiguration.RequestIdKey.ShouldBe(expecteds.GlobalConfiguration.RequestIdKey);
 | 
			
		||||
            response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Host);
 | 
			
		||||
            response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Port);
 | 
			
		||||
 | 
			
		||||
            for (var i = 0; i < response.ReRoutes.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                for (var j = 0; j < response.ReRoutes[i].DownstreamHostAndPorts.Count; j++)
 | 
			
		||||
                {
 | 
			
		||||
                    var result = response.ReRoutes[i].DownstreamHostAndPorts[j];
 | 
			
		||||
                    var expected = expecteds.ReRoutes[i].DownstreamHostAndPorts[j];
 | 
			
		||||
                    result.Host.ShouldBe(expected.Host);
 | 
			
		||||
                    result.Port.ShouldBe(expected.Port);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                response.ReRoutes[i].DownstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].DownstreamPathTemplate);
 | 
			
		||||
                response.ReRoutes[i].DownstreamScheme.ShouldBe(expecteds.ReRoutes[i].DownstreamScheme);
 | 
			
		||||
                response.ReRoutes[i].UpstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].UpstreamPathTemplate);
 | 
			
		||||
                response.ReRoutes[i].UpstreamHttpMethod.ShouldBe(expecteds.ReRoutes[i].UpstreamHttpMethod);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void GivenOcelotIsRunning(OcelotPipelineConfiguration ocelotPipelineConfig)
 | 
			
		||||
        {
 | 
			
		||||
            var builder = new ConfigurationBuilder()
 | 
			
		||||
                .SetBasePath(Directory.GetCurrentDirectory())
 | 
			
		||||
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
 | 
			
		||||
                .AddJsonFile("configuration.json")
 | 
			
		||||
                .AddEnvironmentVariables();
 | 
			
		||||
 | 
			
		||||
            var configuration = builder.Build();
 | 
			
		||||
            _webHostBuilder = new WebHostBuilder();
 | 
			
		||||
            _webHostBuilder.ConfigureServices(s =>
 | 
			
		||||
            {
 | 
			
		||||
                s.AddSingleton(_webHostBuilder);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            _ocelotServer = new TestServer(_webHostBuilder
 | 
			
		||||
                .UseConfiguration(configuration)
 | 
			
		||||
                .ConfigureServices(s =>
 | 
			
		||||
                {
 | 
			
		||||
                    Action<ConfigurationBuilderCachePart> settings = (x) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        x.WithMicrosoftLogging(log =>
 | 
			
		||||
                        {
 | 
			
		||||
                            log.AddConsole(LogLevel.Debug);
 | 
			
		||||
                        })
 | 
			
		||||
                        .WithDictionaryHandle();
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    s.AddOcelot(configuration);
 | 
			
		||||
                })
 | 
			
		||||
                .ConfigureLogging(l =>
 | 
			
		||||
                {
 | 
			
		||||
                    l.AddConsole();
 | 
			
		||||
                    l.AddDebug();
 | 
			
		||||
                })
 | 
			
		||||
                .Configure(a =>
 | 
			
		||||
                {
 | 
			
		||||
                    a.UseOcelot(ocelotPipelineConfig).Wait();
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
            _ocelotClient = _ocelotServer.CreateClient();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenIHaveAddedATokenToMyRequest()
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenIHaveAToken(string url)
 | 
			
		||||
        {
 | 
			
		||||
            var tokenUrl = $"{url}/connect/token";
 | 
			
		||||
            var formData = new List<KeyValuePair<string, string>>
 | 
			
		||||
            {
 | 
			
		||||
                new KeyValuePair<string, string>("client_id", "client"),
 | 
			
		||||
                new KeyValuePair<string, string>("client_secret", "secret"),
 | 
			
		||||
                new KeyValuePair<string, string>("scope", "api"),
 | 
			
		||||
                new KeyValuePair<string, string>("username", "test"),
 | 
			
		||||
                new KeyValuePair<string, string>("password", "test"),
 | 
			
		||||
                new KeyValuePair<string, string>("grant_type", "password")
 | 
			
		||||
            };
 | 
			
		||||
            var content = new FormUrlEncodedContent(formData);
 | 
			
		||||
 | 
			
		||||
            using (var httpClient = new HttpClient())
 | 
			
		||||
            {
 | 
			
		||||
                var response = httpClient.PostAsync(tokenUrl, content).Result;
 | 
			
		||||
                var responseContent = response.Content.ReadAsStringAsync().Result;
 | 
			
		||||
                response.EnsureSuccessStatusCode();
 | 
			
		||||
                _token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenIHaveATokenForApiReadOnlyScope(string url)
 | 
			
		||||
        {
 | 
			
		||||
            var tokenUrl = $"{url}/connect/token";
 | 
			
		||||
            var formData = new List<KeyValuePair<string, string>>
 | 
			
		||||
            {
 | 
			
		||||
                new KeyValuePair<string, string>("client_id", "client"),
 | 
			
		||||
                new KeyValuePair<string, string>("client_secret", "secret"),
 | 
			
		||||
                new KeyValuePair<string, string>("scope", "api.readOnly"),
 | 
			
		||||
                new KeyValuePair<string, string>("username", "test"),
 | 
			
		||||
                new KeyValuePair<string, string>("password", "test"),
 | 
			
		||||
                new KeyValuePair<string, string>("grant_type", "password")
 | 
			
		||||
            };
 | 
			
		||||
            var content = new FormUrlEncodedContent(formData);
 | 
			
		||||
 | 
			
		||||
            using (var httpClient = new HttpClient())
 | 
			
		||||
            {
 | 
			
		||||
                var response = httpClient.PostAsync(tokenUrl, content).Result;
 | 
			
		||||
                var responseContent = response.Content.ReadAsStringAsync().Result;
 | 
			
		||||
                response.EnsureSuccessStatusCode();
 | 
			
		||||
                _token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenIHaveATokenForApi2(string url)
 | 
			
		||||
        {
 | 
			
		||||
            var tokenUrl = $"{url}/connect/token";
 | 
			
		||||
            var formData = new List<KeyValuePair<string, string>>
 | 
			
		||||
            {
 | 
			
		||||
                new KeyValuePair<string, string>("client_id", "client"),
 | 
			
		||||
                new KeyValuePair<string, string>("client_secret", "secret"),
 | 
			
		||||
                new KeyValuePair<string, string>("scope", "api2"),
 | 
			
		||||
                new KeyValuePair<string, string>("username", "test"),
 | 
			
		||||
                new KeyValuePair<string, string>("password", "test"),
 | 
			
		||||
                new KeyValuePair<string, string>("grant_type", "password")
 | 
			
		||||
            };
 | 
			
		||||
            var content = new FormUrlEncodedContent(formData);
 | 
			
		||||
 | 
			
		||||
            using (var httpClient = new HttpClient())
 | 
			
		||||
            {
 | 
			
		||||
                var response = httpClient.PostAsync(tokenUrl, content).Result;
 | 
			
		||||
                var responseContent = response.Content.ReadAsStringAsync().Result;
 | 
			
		||||
                response.EnsureSuccessStatusCode();
 | 
			
		||||
                _token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenIHaveAnOcelotToken(string adminPath)
 | 
			
		||||
        {
 | 
			
		||||
            var tokenUrl = $"{adminPath}/connect/token";
 | 
			
		||||
            var formData = new List<KeyValuePair<string, string>>
 | 
			
		||||
            {
 | 
			
		||||
                new KeyValuePair<string, string>("client_id", "admin"),
 | 
			
		||||
                new KeyValuePair<string, string>("client_secret", "secret"),
 | 
			
		||||
                new KeyValuePair<string, string>("scope", "admin"),
 | 
			
		||||
                new KeyValuePair<string, string>("username", "admin"),
 | 
			
		||||
                new KeyValuePair<string, string>("password", "admin"),
 | 
			
		||||
                new KeyValuePair<string, string>("grant_type", "password")
 | 
			
		||||
            };
 | 
			
		||||
            var content = new FormUrlEncodedContent(formData);
 | 
			
		||||
 | 
			
		||||
            var response = _ocelotClient.PostAsync(tokenUrl, content).Result;
 | 
			
		||||
            var responseContent = response.Content.ReadAsStringAsync().Result;
 | 
			
		||||
            response.EnsureSuccessStatusCode();
 | 
			
		||||
            _token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void VerifyIdentiryServerStarted(string url)
 | 
			
		||||
        {
 | 
			
		||||
            using (var httpClient = new HttpClient())
 | 
			
		||||
            {
 | 
			
		||||
                var response = httpClient.GetAsync($"{url}/.well-known/openid-configuration").Result;
 | 
			
		||||
                response.EnsureSuccessStatusCode();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WhenIGetUrlOnTheApiGateway(string url)
 | 
			
		||||
        {
 | 
			
		||||
            _response = _ocelotClient.GetAsync(url).Result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenIAddAHeader(string key, string value)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotClient.DefaultRequestHeaders.Add(key, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WhenIGetUrlOnTheApiGatewayMultipleTimes(string url, int times)
 | 
			
		||||
        {
 | 
			
		||||
            var tasks = new Task[times];
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < times; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var urlCopy = url;
 | 
			
		||||
                tasks[i] = GetForServiceDiscoveryTest(urlCopy);
 | 
			
		||||
                Thread.Sleep(_random.Next(40, 60));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Task.WaitAll(tasks);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task GetForServiceDiscoveryTest(string url)
 | 
			
		||||
        {
 | 
			
		||||
            var response = await _ocelotClient.GetAsync(url);
 | 
			
		||||
            var content = await response.Content.ReadAsStringAsync();
 | 
			
		||||
            int count = int.Parse(content);
 | 
			
		||||
            count.ShouldBeGreaterThan(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit(string url, int times)
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < times; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var clientId = "ocelotclient1";
 | 
			
		||||
                var request = new HttpRequestMessage(new HttpMethod("GET"), url);
 | 
			
		||||
                request.Headers.Add("ClientId", clientId);
 | 
			
		||||
                _response = _ocelotClient.SendAsync(request).Result;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WhenIGetUrlOnTheApiGateway(string url, string requestId)
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotClient.DefaultRequestHeaders.TryAddWithoutValidation(RequestIdKey, requestId);
 | 
			
		||||
 | 
			
		||||
            _response = _ocelotClient.GetAsync(url).Result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WhenIPostUrlOnTheApiGateway(string url)
 | 
			
		||||
        {
 | 
			
		||||
            _response = _ocelotClient.PostAsync(url, _postContent).Result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenThePostHasContent(string postcontent)
 | 
			
		||||
        {
 | 
			
		||||
            _postContent = new StringContent(postcontent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void GivenThePostHasGzipContent(object input)
 | 
			
		||||
        {
 | 
			
		||||
            string json = JsonConvert.SerializeObject(input);
 | 
			
		||||
            byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
 | 
			
		||||
            MemoryStream ms = new MemoryStream();
 | 
			
		||||
            using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
 | 
			
		||||
            {
 | 
			
		||||
                gzip.Write(jsonBytes, 0, jsonBytes.Length);
 | 
			
		||||
            }
 | 
			
		||||
            ms.Position = 0;
 | 
			
		||||
            StreamContent content = new StreamContent(ms);
 | 
			
		||||
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
 | 
			
		||||
            content.Headers.ContentEncoding.Add("gzip");
 | 
			
		||||
            _postContent = content;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheResponseBodyShouldBe(string expectedBody)
 | 
			
		||||
        {
 | 
			
		||||
            _response.Content.ReadAsStringAsync().Result.ShouldBe(expectedBody);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
 | 
			
		||||
        {
 | 
			
		||||
            _response.StatusCode.ShouldBe(expectedHttpStatusCode);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheStatusCodeShouldBe(int expectedHttpStatusCode)
 | 
			
		||||
        {
 | 
			
		||||
            var responseStatusCode = (int)_response.StatusCode;
 | 
			
		||||
            responseStatusCode.ShouldBe(expectedHttpStatusCode);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            _ocelotClient?.Dispose();
 | 
			
		||||
            _ocelotServer?.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheRequestIdIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            _response.Headers.GetValues(RequestIdKey).First().ShouldNotBeNullOrEmpty();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheRequestIdIsReturned(string expected)
 | 
			
		||||
        {
 | 
			
		||||
            _response.Headers.GetValues(RequestIdKey).First().ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ThenTheContentLengthIs(int expected)
 | 
			
		||||
        {
 | 
			
		||||
            _response.Content.Headers.ContentLength.ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WhenIMakeLotsOfDifferentRequestsToTheApiGateway()
 | 
			
		||||
        {
 | 
			
		||||
            int numberOfRequests = 100;
 | 
			
		||||
            var aggregateUrl = "/";
 | 
			
		||||
            var aggregateExpected = "{\"Laura\":{Hello from Laura},\"Tom\":{Hello from Tom}}";
 | 
			
		||||
            var tomUrl = "/tom";
 | 
			
		||||
            var tomExpected = "{Hello from Tom}";
 | 
			
		||||
            var lauraUrl = "/laura";
 | 
			
		||||
            var lauraExpected = "{Hello from Laura}";
 | 
			
		||||
            var random = new Random();
 | 
			
		||||
 | 
			
		||||
            var aggregateTasks = new Task[numberOfRequests];
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < numberOfRequests; i++)
 | 
			
		||||
            {
 | 
			
		||||
                aggregateTasks[i] = Fire(aggregateUrl, aggregateExpected, random);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var tomTasks = new Task[numberOfRequests];
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < numberOfRequests; i++)
 | 
			
		||||
            {
 | 
			
		||||
                tomTasks[i] = Fire(tomUrl, tomExpected, random);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var lauraTasks = new Task[numberOfRequests];
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < numberOfRequests; i++)
 | 
			
		||||
            {
 | 
			
		||||
                lauraTasks[i] = Fire(lauraUrl, lauraExpected, random);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Task.WaitAll(lauraTasks);
 | 
			
		||||
            Task.WaitAll(tomTasks);
 | 
			
		||||
            Task.WaitAll(aggregateTasks);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task Fire(string url, string expectedBody, Random random)
 | 
			
		||||
        {
 | 
			
		||||
            var request = new HttpRequestMessage(new HttpMethod("GET"), url);
 | 
			
		||||
            await Task.Delay(random.Next(0, 2));
 | 
			
		||||
            var response = await _ocelotClient.SendAsync(request);
 | 
			
		||||
            var content = await response.Content.ReadAsStringAsync();
 | 
			
		||||
            content.ShouldBe(expectedBody);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -37,7 +37,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public async Task should_proxy_websocket_input_to_downstream_service()
 | 
			
		||||
        public void should_proxy_websocket_input_to_downstream_service()
 | 
			
		||||
        {
 | 
			
		||||
            var downstreamPort = 5001;
 | 
			
		||||
            var downstreamHost = "localhost";
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public async Task should_proxy_websocket_input_to_downstream_service_and_use_load_balancer()
 | 
			
		||||
        public void should_proxy_websocket_input_to_downstream_service_and_use_load_balancer()
 | 
			
		||||
        {
 | 
			
		||||
            var downstreamPort = 5005;
 | 
			
		||||
            var downstreamHost = "localhost";
 | 
			
		||||
@@ -116,7 +116,7 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public async Task should_proxy_websocket_input_to_downstream_service_and_use_service_discovery_and_load_balancer()
 | 
			
		||||
        public void should_proxy_websocket_input_to_downstream_service_and_use_service_discovery_and_load_balancer()
 | 
			
		||||
        {
 | 
			
		||||
            var downstreamPort = 5007;
 | 
			
		||||
            var downstreamHost = "localhost";
 | 
			
		||||
@@ -274,7 +274,6 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                    {
 | 
			
		||||
                        _firstRecieved.Add(Encoding.UTF8.GetString(buffer, 0, result.Count));
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    else if (result.MessageType == WebSocketMessageType.Close)
 | 
			
		||||
                    {
 | 
			
		||||
                        await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
 | 
			
		||||
@@ -321,7 +320,6 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
                    {
 | 
			
		||||
                        _secondRecieved.Add(Encoding.UTF8.GetString(buffer, 0, result.Count));
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    else if (result.MessageType == WebSocketMessageType.Close)
 | 
			
		||||
                    {
 | 
			
		||||
                        await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
 | 
			
		||||
@@ -333,7 +331,6 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
            await Task.WhenAll(sending, receiving);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private async Task StartFakeDownstreamService(string url, string path)
 | 
			
		||||
        {
 | 
			
		||||
            _firstDownstreamHost = new WebHostBuilder()
 | 
			
		||||
@@ -380,7 +377,6 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
            await _firstDownstreamHost.StartAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private async Task StartSecondFakeDownstreamService(string url, string path)
 | 
			
		||||
        {
 | 
			
		||||
            _secondDownstreamHost = new WebHostBuilder()
 | 
			
		||||
@@ -427,7 +423,6 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
            await _secondDownstreamHost.StartAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private async Task Echo(WebSocket webSocket)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="BenchmarkDotNet" Version="0.10.12" />
 | 
			
		||||
    <PackageReference Include="BenchmarkDotNet" Version="0.10.13" />
 | 
			
		||||
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,26 +25,26 @@
 | 
			
		||||
    <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
 | 
			
		||||
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
 | 
			
		||||
    <PackageReference Include="xunit" Version="2.3.1" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4" Version="2.0.2" />
 | 
			
		||||
    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4" Version="2.1.3" />
 | 
			
		||||
    <PackageReference Include="Shouldly" Version="3.0.0" />
 | 
			
		||||
    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.3" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.4" />
 | 
			
		||||
    <PackageReference Include="Rafty" Version="0.4.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Data.SQLite" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Data.SQLite" Version="2.0.1" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -21,19 +21,19 @@
 | 
			
		||||
    </None>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj"/>
 | 
			
		||||
    <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0"/>
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.3"/>
 | 
			
		||||
    <PackageReference Include="Polly" Version="5.3.1"/>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.4" />
 | 
			
		||||
    <PackageReference Include="Polly" Version="5.8.0" />
 | 
			
		||||
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class ServiceProviderCreatorTests
 | 
			
		||||
    {
 | 
			
		||||
        private ServiceProviderConfigurationCreator _creator;
 | 
			
		||||
        private FileReRoute _reRoute;
 | 
			
		||||
        private readonly ServiceProviderConfigurationCreator _creator;
 | 
			
		||||
        private FileGlobalConfiguration _globalConfig;
 | 
			
		||||
        private ServiceProviderConfiguration _result;
 | 
			
		||||
 | 
			
		||||
@@ -23,36 +22,30 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_service_provider_config()
 | 
			
		||||
        {
 | 
			
		||||
            var reRoute = new FileReRoute();
 | 
			
		||||
            
 | 
			
		||||
            var globalConfig = new FileGlobalConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
 | 
			
		||||
                {
 | 
			
		||||
                    Host = "127.0.0.1",
 | 
			
		||||
                    Port = 1234,
 | 
			
		||||
                    Type = "ServiceFabric"
 | 
			
		||||
                    Type = "ServiceFabric",
 | 
			
		||||
                    Token = "testtoken"
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            var expected = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderHost("127.0.0.1")
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(1234)
 | 
			
		||||
                .WithServiceDiscoveryProviderType("ServiceFabric")
 | 
			
		||||
                .WithHost("127.0.0.1")
 | 
			
		||||
                .WithPort(1234)
 | 
			
		||||
                .WithType("ServiceFabric")
 | 
			
		||||
                .WithToken("testtoken")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingReRoute(reRoute))
 | 
			
		||||
                .And(x => x.GivenTheFollowingGlobalConfig(globalConfig))
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingGlobalConfig(globalConfig))
 | 
			
		||||
                .When(x => x.WhenICreate())
 | 
			
		||||
                .Then(x => x.ThenTheConfigIs(expected))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheFollowingReRoute(FileReRoute fileReRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _reRoute = fileReRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheFollowingGlobalConfig(FileGlobalConfiguration fileGlobalConfig)
 | 
			
		||||
        {
 | 
			
		||||
            _globalConfig = fileGlobalConfig;
 | 
			
		||||
@@ -67,6 +60,8 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        {
 | 
			
		||||
            _result.Host.ShouldBe(expected.Host);
 | 
			
		||||
            _result.Port.ShouldBe(expected.Port);
 | 
			
		||||
            _result.Token.ShouldBe(expected.Token);
 | 
			
		||||
            _result.Type.ShouldBe(expected.Type);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -82,9 +82,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var config = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderType("ServiceFabric")
 | 
			
		||||
                .WithServiceDiscoveryProviderHost("localhost")
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(19081)
 | 
			
		||||
                .WithType("ServiceFabric")
 | 
			
		||||
                .WithHost("localhost")
 | 
			
		||||
                .WithPort(19081)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheDownStreamRouteIs(
 | 
			
		||||
@@ -118,9 +118,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
 | 
			
		||||
                    .Build());
 | 
			
		||||
 | 
			
		||||
            var config = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderType("ServiceFabric")
 | 
			
		||||
                .WithServiceDiscoveryProviderHost("localhost")
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(19081)
 | 
			
		||||
                .WithType("ServiceFabric")
 | 
			
		||||
                .WithHost("localhost")
 | 
			
		||||
                .WithPort(19081)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
			
		||||
@@ -148,9 +148,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
 | 
			
		||||
                    .Build());
 | 
			
		||||
 | 
			
		||||
            var config = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderType("ServiceFabric")
 | 
			
		||||
                .WithServiceDiscoveryProviderHost("localhost")
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(19081)
 | 
			
		||||
                .WithType("ServiceFabric")
 | 
			
		||||
                .WithHost("localhost")
 | 
			
		||||
                .WithPort(19081)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
			
		||||
@@ -178,9 +178,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
 | 
			
		||||
                    .Build());
 | 
			
		||||
 | 
			
		||||
            var config = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderType("ServiceFabric")
 | 
			
		||||
                .WithServiceDiscoveryProviderHost("localhost")
 | 
			
		||||
                .WithServiceDiscoveryProviderPort(19081)
 | 
			
		||||
                .WithType("ServiceFabric")
 | 
			
		||||
                .WithHost("localhost")
 | 
			
		||||
                .WithPort(19081)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
        {
 | 
			
		||||
            _factory = new Mock<ILoadBalancerFactory>();
 | 
			
		||||
            _loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
 | 
			
		||||
            _serviceProviderConfig = new ServiceProviderConfiguration("myType","myHost",123);
 | 
			
		||||
            _serviceProviderConfig = new ServiceProviderConfiguration("myType","myHost",123, string.Empty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
 
 | 
			
		||||
@@ -35,23 +35,23 @@
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
 | 
			
		||||
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
			
		||||
    <PackageReference Include="Moq" Version="4.7.142" />
 | 
			
		||||
    <PackageReference Include="Shouldly" Version="3.0.0-beta0003" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
 | 
			
		||||
    <PackageReference Include="Moq" Version="4.8.2" />
 | 
			
		||||
    <PackageReference Include="Shouldly" Version="3.0.0" />
 | 
			
		||||
    <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
 | 
			
		||||
    <PackageReference Include="xunit" Version="2.3.1" />
 | 
			
		||||
    <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Consul;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Infrastructure.Consul;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.ServiceDiscovery;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Configuration;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Providers;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
@@ -22,14 +22,16 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
    {
 | 
			
		||||
        private IWebHost _fakeConsulBuilder;
 | 
			
		||||
        private readonly List<ServiceEntry> _serviceEntries;
 | 
			
		||||
        private readonly ConsulServiceDiscoveryProvider _provider;
 | 
			
		||||
        private ConsulServiceDiscoveryProvider _provider;
 | 
			
		||||
        private readonly string _serviceName;
 | 
			
		||||
        private readonly int _port;
 | 
			
		||||
        private readonly string _consulHost;
 | 
			
		||||
        private readonly string _fakeConsulServiceDiscoveryUrl;
 | 
			
		||||
        private List<Service> _services;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _factory;
 | 
			
		||||
        private readonly Mock<IOcelotLoggerFactory> _factory;
 | 
			
		||||
        private readonly Mock<IOcelotLogger> _logger;
 | 
			
		||||
        private string _receivedToken;
 | 
			
		||||
        private IConsulClientFactory _clientFactory;
 | 
			
		||||
 | 
			
		||||
        public ConsulServiceDiscoveryProviderTests()
 | 
			
		||||
        {
 | 
			
		||||
@@ -40,11 +42,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
            _serviceEntries = new List<ServiceEntry>();
 | 
			
		||||
 | 
			
		||||
            _factory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            _clientFactory = new ConsulClientFactory();
 | 
			
		||||
            _logger = new Mock<IOcelotLogger>();
 | 
			
		||||
            _factory.Setup(x => x.CreateLogger<ConsulServiceDiscoveryProvider>()).Returns(_logger.Object);
 | 
			
		||||
 | 
			
		||||
            var config = new ConsulRegistryConfiguration(_consulHost, _port, _serviceName);
 | 
			
		||||
            _provider = new ConsulServiceDiscoveryProvider(config, _factory.Object);
 | 
			
		||||
            var config = new ConsulRegistryConfiguration(_consulHost, _port, _serviceName, null);
 | 
			
		||||
            _provider = new ConsulServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -69,6 +72,33 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_token()
 | 
			
		||||
        {
 | 
			
		||||
            var token = "test token";
 | 
			
		||||
            var config = new ConsulRegistryConfiguration(_consulHost, _port, _serviceName, token);
 | 
			
		||||
            _provider = new ConsulServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
 | 
			
		||||
 | 
			
		||||
            var serviceEntryOne = new ServiceEntry()
 | 
			
		||||
            {
 | 
			
		||||
                Service = new AgentService()
 | 
			
		||||
                {
 | 
			
		||||
                    Service = _serviceName,
 | 
			
		||||
                    Address = "localhost",
 | 
			
		||||
                    Port = 50881,
 | 
			
		||||
                    ID = Guid.NewGuid().ToString(),
 | 
			
		||||
                    Tags = new string[0]
 | 
			
		||||
                },
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
 | 
			
		||||
                .And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
 | 
			
		||||
                .When(_ => WhenIGetTheServices())
 | 
			
		||||
                .Then(_ => ThenTheCountIs(1))
 | 
			
		||||
                .And(_ => _receivedToken.ShouldBe(token))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_return_services_with_invalid_address()
 | 
			
		||||
        {
 | 
			
		||||
@@ -197,6 +227,11 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
                    {
 | 
			
		||||
                        if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
 | 
			
		||||
                        {
 | 
			
		||||
                            if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
 | 
			
		||||
                            {
 | 
			
		||||
                                _receivedToken = values.First();
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            await context.Response.WriteJsonAsync(_serviceEntries);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Infrastructure.Consul;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.ServiceDiscovery;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Providers;
 | 
			
		||||
@@ -19,11 +20,13 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
        private readonly ServiceDiscoveryProviderFactory _factory;
 | 
			
		||||
        private DownstreamReRoute _reRoute;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private IConsulClientFactory _clientFactory;
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderFactoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            _factory = new ServiceDiscoveryProviderFactory(_loggerFactory.Object);
 | 
			
		||||
            _clientFactory = new ConsulClientFactory();
 | 
			
		||||
            _factory = new ServiceDiscoveryProviderFactory(_loggerFactory.Object, _clientFactory);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -87,7 +90,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var serviceConfig = new ServiceProviderConfigurationBuilder()
 | 
			
		||||
                .WithServiceDiscoveryProviderType("ServiceFabric")
 | 
			
		||||
                .WithType("ServiceFabric")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user