mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 10:35:28 +08:00 
			
		
		
		
	Monitoring (#219)
* feat: use Https://github.com/ButterflyAPM to monitor each API request monitoring metrics * feat: using DiagnosticSource and Butterfly.OpenTracing * refactor:refactor Ocelot tracing, merge code into OcelotDiagnosticListener * refactor: move OcelotHttpTracingHandler to Requester * fix: Requester\HttpClientBuilder.cs(10,14): error CS0234: The type or namespace name 'Tracing' does not exist in the namespace * feat: add test should_set_up_tracing * feat : Remove extraneous code * feat: remove unused DiagnosticSource diagnostic * fix : test UseTracing * add test should_call_scoped_data_repository_QosProviderError * add test should_return_any_errors * add test HttpClientHttpRequesterTest * it should keep it can not be deleted
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Microsoft Visual Studio Solution File, Format Version 12.00
 | 
					Microsoft Visual Studio Solution File, Format Version 12.00
 | 
				
			||||||
# Visual Studio 15
 | 
					# Visual Studio 15
 | 
				
			||||||
VisualStudioVersion = 15.0.26730.15
 | 
					VisualStudioVersion = 15.0.27130.2024
 | 
				
			||||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
					MinimumVisualStudioVersion = 10.0.40219.1
 | 
				
			||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5CFB79B7-C9DC-45A4-9A75-625D92471702}"
 | 
					Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5CFB79B7-C9DC-45A4-9A75-625D92471702}"
 | 
				
			||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ namespace Ocelot.Configuration.Creator
 | 
				
			|||||||
        public HttpHandlerOptions Create(FileReRoute fileReRoute)
 | 
					        public HttpHandlerOptions Create(FileReRoute fileReRoute)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new HttpHandlerOptions(fileReRoute.HttpHandlerOptions.AllowAutoRedirect,
 | 
					            return new HttpHandlerOptions(fileReRoute.HttpHandlerOptions.AllowAutoRedirect,
 | 
				
			||||||
                fileReRoute.HttpHandlerOptions.UseCookieContainer);
 | 
					                fileReRoute.HttpHandlerOptions.UseCookieContainer, fileReRoute.HttpHandlerOptions.UseTracing);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,5 +11,7 @@
 | 
				
			|||||||
        public bool AllowAutoRedirect { get; set; }
 | 
					        public bool AllowAutoRedirect { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool UseCookieContainer { get; set; }
 | 
					        public bool UseCookieContainer { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool UseTracing { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,10 +6,11 @@
 | 
				
			|||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public class HttpHandlerOptions
 | 
					    public class HttpHandlerOptions
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public HttpHandlerOptions(bool allowAutoRedirect, bool useCookieContainer)
 | 
					        public HttpHandlerOptions(bool allowAutoRedirect, bool useCookieContainer, bool useTracing)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            AllowAutoRedirect = allowAutoRedirect;
 | 
					            AllowAutoRedirect = allowAutoRedirect;
 | 
				
			||||||
            UseCookieContainer = useCookieContainer;
 | 
					            UseCookieContainer = useCookieContainer;
 | 
				
			||||||
 | 
					            UseTracing = useTracing;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@@ -21,5 +22,10 @@
 | 
				
			|||||||
        /// Specify is handler has to use a cookie container
 | 
					        /// Specify is handler has to use a cookie container
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public bool UseCookieContainer { get; private set; }
 | 
					        public bool UseCookieContainer { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // <summary>
 | 
				
			||||||
 | 
					        /// Specify is handler has to use a opentracing
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public bool UseTracing { get; private set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					using Butterfly.Client.AspNetCore;
 | 
				
			||||||
using CacheManager.Core;
 | 
					using CacheManager.Core;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7,6 +8,7 @@ namespace Ocelot.DependencyInjection
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        IOcelotBuilder AddStoreOcelotConfigurationInConsul();
 | 
					        IOcelotBuilder AddStoreOcelotConfigurationInConsul();
 | 
				
			||||||
        IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
 | 
					        IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
 | 
				
			||||||
 | 
					        IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings);      
 | 
				
			||||||
        IOcelotAdministrationBuilder AddAdministration(string path, string secret);
 | 
					        IOcelotAdministrationBuilder AddAdministration(string path, string secret);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,19 @@
 | 
				
			|||||||
 | 
					using Butterfly.Client.AspNetCore;
 | 
				
			||||||
using CacheManager.Core;
 | 
					using CacheManager.Core;
 | 
				
			||||||
 | 
					using IdentityServer4.AccessTokenValidation;
 | 
				
			||||||
using IdentityServer4.Models;
 | 
					using IdentityServer4.Models;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
using Microsoft.Extensions.Configuration;
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
using Microsoft.Extensions.DependencyInjection;
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.DependencyInjection.Extensions;
 | 
				
			||||||
using Ocelot.Authorisation;
 | 
					using Ocelot.Authorisation;
 | 
				
			||||||
using Ocelot.Cache;
 | 
					using Ocelot.Cache;
 | 
				
			||||||
using Ocelot.Claims;
 | 
					using Ocelot.Claims;
 | 
				
			||||||
 | 
					using Ocelot.Configuration;
 | 
				
			||||||
using Ocelot.Configuration.Authentication;
 | 
					using Ocelot.Configuration.Authentication;
 | 
				
			||||||
 | 
					using Ocelot.Configuration.Builder;
 | 
				
			||||||
using Ocelot.Configuration.Creator;
 | 
					using Ocelot.Configuration.Creator;
 | 
				
			||||||
using Ocelot.Configuration.File;
 | 
					using Ocelot.Configuration.File;
 | 
				
			||||||
using Ocelot.Configuration.Parser;
 | 
					using Ocelot.Configuration.Parser;
 | 
				
			||||||
@@ -25,6 +32,7 @@ using Ocelot.LoadBalancer.LoadBalancers;
 | 
				
			|||||||
using Ocelot.Logging;
 | 
					using Ocelot.Logging;
 | 
				
			||||||
using Ocelot.Middleware;
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
using Ocelot.QueryStrings;
 | 
					using Ocelot.QueryStrings;
 | 
				
			||||||
 | 
					using Ocelot.Raft;
 | 
				
			||||||
using Ocelot.RateLimit;
 | 
					using Ocelot.RateLimit;
 | 
				
			||||||
using Ocelot.Request.Builder;
 | 
					using Ocelot.Request.Builder;
 | 
				
			||||||
using Ocelot.Request.Mapper;
 | 
					using Ocelot.Request.Mapper;
 | 
				
			||||||
@@ -32,26 +40,17 @@ using Ocelot.Requester;
 | 
				
			|||||||
using Ocelot.Requester.QoS;
 | 
					using Ocelot.Requester.QoS;
 | 
				
			||||||
using Ocelot.Responder;
 | 
					using Ocelot.Responder;
 | 
				
			||||||
using Ocelot.ServiceDiscovery;
 | 
					using Ocelot.ServiceDiscovery;
 | 
				
			||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.IdentityModel.Tokens.Jwt;
 | 
					 | 
				
			||||||
using System.Net.Http;
 | 
					 | 
				
			||||||
using System.Reflection;
 | 
					 | 
				
			||||||
using System.Security.Cryptography.X509Certificates;
 | 
					 | 
				
			||||||
using IdentityServer4.AccessTokenValidation;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Builder;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Hosting;
 | 
					 | 
				
			||||||
using Ocelot.Configuration;
 | 
					 | 
				
			||||||
using Ocelot.Configuration.Builder;
 | 
					 | 
				
			||||||
using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
 | 
					 | 
				
			||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using Ocelot.Raft;
 | 
					 | 
				
			||||||
using Rafty.Concensus;
 | 
					using Rafty.Concensus;
 | 
				
			||||||
using Rafty.FiniteStateMachine;
 | 
					using Rafty.FiniteStateMachine;
 | 
				
			||||||
using Rafty.Infrastructure;
 | 
					using Rafty.Infrastructure;
 | 
				
			||||||
using Rafty.Log;
 | 
					using Rafty.Log;
 | 
				
			||||||
using Newtonsoft.Json;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IdentityModel.Tokens.Jwt;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Security.Cryptography.X509Certificates;
 | 
				
			||||||
 | 
					using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.DependencyInjection
 | 
					namespace Ocelot.DependencyInjection
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -204,6 +203,13 @@ namespace Ocelot.DependencyInjection
 | 
				
			|||||||
            return this;
 | 
					            return this;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _services.AddTransient<OcelotHttpTracingHandler>();
 | 
				
			||||||
 | 
					            _services.AddButterfly(settings);   
 | 
				
			||||||
 | 
					            return this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath) 
 | 
					        private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath) 
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
 | 
					            _services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
using Microsoft.Extensions.DiagnosticAdapter;
 | 
					using Microsoft.Extensions.DiagnosticAdapter;
 | 
				
			||||||
 | 
					using Butterfly.Client.AspNetCore;
 | 
				
			||||||
 | 
					using Butterfly.OpenTracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Logging
 | 
					namespace Ocelot.Logging
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -17,6 +19,7 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        public virtual void OnMiddlewareStarting(HttpContext httpContext, string name)
 | 
					        public virtual void OnMiddlewareStarting(HttpContext httpContext, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogTrace($"MiddlewareStarting: {name}; {httpContext.Request.Path}");
 | 
					            _logger.LogTrace($"MiddlewareStarting: {name}; {httpContext.Request.Path}");
 | 
				
			||||||
 | 
					            Event(httpContext, $"MiddlewareStarting: {name}; {httpContext.Request.Path}");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
 | 
					        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
 | 
				
			||||||
@@ -29,6 +32,13 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        public virtual void OnMiddlewareFinished(HttpContext httpContext, string name)
 | 
					        public virtual void OnMiddlewareFinished(HttpContext httpContext, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogTrace($"MiddlewareFinished: {name}; {httpContext.Response.StatusCode}");
 | 
					            _logger.LogTrace($"MiddlewareFinished: {name}; {httpContext.Response.StatusCode}");
 | 
				
			||||||
 | 
					            Event(httpContext, $"MiddlewareFinished: {name}; {httpContext.Response.StatusCode}");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void Event(HttpContext httpContext, string @event)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var span = httpContext.GetSpan();
 | 
				
			||||||
 | 
					            span?.Log(LogField.CreateNew().Event(@event));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,24 +23,25 @@
 | 
				
			|||||||
    <DebugSymbols>True</DebugSymbols>
 | 
					    <DebugSymbols>True</DebugSymbols>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  </PropertyGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <PackageReference Include="FluentValidation" Version="7.2.1"/>
 | 
					    <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.5" />
 | 
				
			||||||
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0"/>
 | 
					    <PackageReference Include="FluentValidation" Version="7.2.1" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0"/>
 | 
					    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0"/>
 | 
					    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0"/>
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0"/>
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" 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.DiagnosticAdapter" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0"/>
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0"/>
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0"/>
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="System.Text.RegularExpressions" Version="4.3.0"/>
 | 
					    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
 | 
				
			||||||
    <PackageReference Include="CacheManager.Core" Version="1.1.1"/>
 | 
					    <PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
 | 
				
			||||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.1"/>
 | 
					    <PackageReference Include="CacheManager.Core" Version="1.1.1" />
 | 
				
			||||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.1"/>
 | 
					    <PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.1" />
 | 
				
			||||||
    <PackageReference Include="Consul" Version="0.7.2.3"/>
 | 
					    <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.1" />
 | 
				
			||||||
    <PackageReference Include="Polly" Version="5.3.1"/>
 | 
					    <PackageReference Include="Consul" Version="0.7.2.3" />
 | 
				
			||||||
    <PackageReference Include="IdentityServer4" Version="2.0.2"/>
 | 
					    <PackageReference Include="Polly" Version="5.3.1" />
 | 
				
			||||||
    <PackageReference Include="Rafty" Version="0.4.2"/>
 | 
					    <PackageReference Include="IdentityServer4" Version="2.0.2" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Rafty" Version="0.4.2" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
</Project>
 | 
					</Project>
 | 
				
			||||||
@@ -12,9 +12,10 @@ namespace Ocelot.Request.Builder
 | 
				
			|||||||
            bool isQos,
 | 
					            bool isQos,
 | 
				
			||||||
            IQoSProvider qosProvider,
 | 
					            IQoSProvider qosProvider,
 | 
				
			||||||
            bool useCookieContainer,
 | 
					            bool useCookieContainer,
 | 
				
			||||||
            bool allowAutoRedirect)
 | 
					            bool allowAutoRedirect,
 | 
				
			||||||
 | 
					            bool isTracing)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider, allowAutoRedirect, useCookieContainer));
 | 
					            return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider, allowAutoRedirect, useCookieContainer, isTracing));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -13,6 +13,7 @@
 | 
				
			|||||||
            bool isQos,
 | 
					            bool isQos,
 | 
				
			||||||
            IQoSProvider qosProvider,
 | 
					            IQoSProvider qosProvider,
 | 
				
			||||||
            bool useCookieContainer,
 | 
					            bool useCookieContainer,
 | 
				
			||||||
            bool allowAutoRedirect);
 | 
					            bool allowAutoRedirect,
 | 
				
			||||||
 | 
					            bool isTracing);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,16 +46,15 @@ namespace Ocelot.Request.Middleware
 | 
				
			|||||||
                    DownstreamRoute.ReRoute.IsQos,
 | 
					                    DownstreamRoute.ReRoute.IsQos,
 | 
				
			||||||
                    qosProvider.Data,
 | 
					                    qosProvider.Data,
 | 
				
			||||||
                    DownstreamRoute.ReRoute.HttpHandlerOptions.UseCookieContainer,
 | 
					                    DownstreamRoute.ReRoute.HttpHandlerOptions.UseCookieContainer,
 | 
				
			||||||
                    DownstreamRoute.ReRoute.HttpHandlerOptions.AllowAutoRedirect);
 | 
					                    DownstreamRoute.ReRoute.HttpHandlerOptions.AllowAutoRedirect,
 | 
				
			||||||
 | 
					                    DownstreamRoute.ReRoute.HttpHandlerOptions.UseTracing);
 | 
				
			||||||
            if (buildResult.IsError)
 | 
					            if (buildResult.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("IRequestCreator returned an error, setting pipeline error");
 | 
					                _logger.LogDebug("IRequestCreator returned an error, setting pipeline error");
 | 
				
			||||||
 | 
					 | 
				
			||||||
                SetPipelineError(buildResult.Errors);
 | 
					                SetPipelineError(buildResult.Errors);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("setting upstream request");
 | 
					            _logger.LogDebug("setting upstream request");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SetUpstreamRequestForThisRequest(buildResult.Data);
 | 
					            SetUpstreamRequestForThisRequest(buildResult.Data);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,17 +10,21 @@ namespace Ocelot.Request
 | 
				
			|||||||
            bool isQos,
 | 
					            bool isQos,
 | 
				
			||||||
            IQoSProvider qosProvider, 
 | 
					            IQoSProvider qosProvider, 
 | 
				
			||||||
            bool allowAutoRedirect,
 | 
					            bool allowAutoRedirect,
 | 
				
			||||||
            bool useCookieContainer)
 | 
					            bool useCookieContainer,
 | 
				
			||||||
 | 
					            bool isTracing
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            HttpRequestMessage = httpRequestMessage;
 | 
					            HttpRequestMessage = httpRequestMessage;
 | 
				
			||||||
            IsQos = isQos;
 | 
					            IsQos = isQos;
 | 
				
			||||||
            QosProvider = qosProvider;
 | 
					            QosProvider = qosProvider;
 | 
				
			||||||
            AllowAutoRedirect = allowAutoRedirect;
 | 
					            AllowAutoRedirect = allowAutoRedirect;
 | 
				
			||||||
            UseCookieContainer = useCookieContainer;
 | 
					            UseCookieContainer = useCookieContainer;
 | 
				
			||||||
 | 
					            IsTracing = isTracing;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public HttpRequestMessage HttpRequestMessage { get; private set; }
 | 
					        public HttpRequestMessage HttpRequestMessage { get; private set; }
 | 
				
			||||||
        public bool IsQos { get; private set; }
 | 
					        public bool IsQos { get; private set; }
 | 
				
			||||||
 | 
					        public bool IsTracing { get; private set; }
 | 
				
			||||||
        public IQoSProvider QosProvider { get; private set; }
 | 
					        public IQoSProvider QosProvider { get; private set; }
 | 
				
			||||||
        public bool AllowAutoRedirect { get; private set; }
 | 
					        public bool AllowAutoRedirect { get; private set; }
 | 
				
			||||||
        public bool UseCookieContainer { get; private set; }
 | 
					        public bool UseCookieContainer { get; private set; }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
using System;
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Net;
 | 
					 | 
				
			||||||
using System.Net.Http;
 | 
					 | 
				
			||||||
using System.Threading.Tasks;
 | 
					 | 
				
			||||||
using Ocelot.Logging;
 | 
					using Ocelot.Logging;
 | 
				
			||||||
using Ocelot.Requester.QoS;
 | 
					using Ocelot.Requester.QoS;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Requester
 | 
					namespace Ocelot.Requester
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -20,10 +20,19 @@ namespace Ocelot.Requester
 | 
				
			|||||||
            return this;
 | 
					            return this;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IHttpClient Create(bool useCookies, bool allowAutoRedirect)
 | 
					        private IHttpClientBuilder WithTracing(IServiceProvider provider)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var httpclientHandler = new HttpClientHandler { AllowAutoRedirect = allowAutoRedirect, UseCookies = useCookies};
 | 
					            _handlers.Add(6000, () => provider.GetService<OcelotHttpTracingHandler>());
 | 
				
			||||||
 | 
					            return this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IHttpClient Create(bool useCookies, bool allowAutoRedirect, bool isTracing, IServiceProvider provider)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var httpclientHandler = new HttpClientHandler { AllowAutoRedirect = allowAutoRedirect, UseCookies = useCookies };
 | 
				
			||||||
 | 
					            if (isTracing)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                WithTracing(provider);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            var client = new HttpClient(CreateHttpMessageHandler(httpclientHandler));                
 | 
					            var client = new HttpClient(CreateHttpMessageHandler(httpclientHandler));                
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            return new HttpClientWrapper(client);
 | 
					            return new HttpClientWrapper(client);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,12 +14,13 @@ namespace Ocelot.Requester
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly IHttpClientCache _cacheHandlers;
 | 
					        private readonly IHttpClientCache _cacheHandlers;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					        private readonly IOcelotLogger _logger;
 | 
				
			||||||
 | 
					        private readonly IServiceProvider _serviceProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory, 
 | 
					        public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory, IHttpClientCache cacheHandlers, IServiceProvider provider)
 | 
				
			||||||
            IHttpClientCache cacheHandlers)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
 | 
					            _logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
 | 
				
			||||||
            _cacheHandlers = cacheHandlers;
 | 
					            _cacheHandlers = cacheHandlers;
 | 
				
			||||||
 | 
					            _serviceProvider = provider;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
 | 
					        public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
 | 
				
			||||||
@@ -28,7 +29,7 @@ namespace Ocelot.Requester
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var cacheKey = GetCacheKey(request, builder);
 | 
					            var cacheKey = GetCacheKey(request, builder);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            var httpClient = GetHttpClient(cacheKey, builder, request.UseCookieContainer, request.AllowAutoRedirect);
 | 
					            var httpClient = GetHttpClient(cacheKey, builder, request.UseCookieContainer, request.AllowAutoRedirect, request.IsTracing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -56,13 +57,13 @@ namespace Ocelot.Requester
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, bool useCookieContainer, bool allowAutoRedirect)
 | 
					        private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, bool useCookieContainer, bool allowAutoRedirect,bool isTracing)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var httpClient = _cacheHandlers.Get(cacheKey);
 | 
					            var httpClient = _cacheHandlers.Get(cacheKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (httpClient == null)
 | 
					            if (httpClient == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                httpClient = builder.Create(useCookieContainer, allowAutoRedirect);
 | 
					                httpClient = builder.Create(useCookieContainer, allowAutoRedirect, isTracing, _serviceProvider);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return httpClient;
 | 
					            return httpClient;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,6 @@ namespace Ocelot.Requester
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="useCookies">Defines if http client should use cookie container</param>
 | 
					        /// <param name="useCookies">Defines if http client should use cookie container</param>
 | 
				
			||||||
        /// <param name="allowAutoRedirect">Defines if http client should allow auto redirect</param>
 | 
					        /// <param name="allowAutoRedirect">Defines if http client should allow auto redirect</param>
 | 
				
			||||||
        IHttpClient Create(bool useCookies, bool allowAutoRedirect);
 | 
					        IHttpClient Create(bool useCookies, bool allowAutoRedirect, bool isTracing, IServiceProvider provider);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,5 @@ namespace Ocelot.Requester
 | 
				
			|||||||
    public interface IHttpRequester
 | 
					    public interface IHttpRequester
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Task<Response<HttpResponseMessage>> GetResponse(Request.Request request);
 | 
					        Task<Response<HttpResponseMessage>> GetResponse(Request.Request request);
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,8 @@
 | 
				
			|||||||
using System.Threading.Tasks;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
using Microsoft.Extensions.Logging;
 | 
					 | 
				
			||||||
using Ocelot.Infrastructure.RequestData;
 | 
					using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
using Ocelot.Logging;
 | 
					using Ocelot.Logging;
 | 
				
			||||||
using Ocelot.Middleware;
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Requester.Middleware
 | 
					namespace Ocelot.Requester.Middleware
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -16,7 +15,8 @@ namespace Ocelot.Requester.Middleware
 | 
				
			|||||||
        public HttpRequesterMiddleware(RequestDelegate next,
 | 
					        public HttpRequesterMiddleware(RequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IHttpRequester requester, 
 | 
					            IHttpRequester requester, 
 | 
				
			||||||
            IRequestScopedDataRepository requestScopedDataRepository)
 | 
					            IRequestScopedDataRepository requestScopedDataRepository
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
            :base(requestScopedDataRepository)
 | 
					            :base(requestScopedDataRepository)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								src/Ocelot/Requester/OcelotHttpTracingHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/Ocelot/Requester/OcelotHttpTracingHandler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Butterfly.Client.Tracing;
 | 
				
			||||||
 | 
					using Butterfly.OpenTracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.Requester
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OcelotHttpTracingHandler : DelegatingHandler
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IServiceTracer _tracer;
 | 
				
			||||||
 | 
					        private const string prefix_spanId = "ot-spanId";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public OcelotHttpTracingHandler(IServiceTracer tracer, HttpMessageHandler httpMessageHandler = null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer));
 | 
				
			||||||
 | 
					            InnerHandler = httpMessageHandler ?? new HttpClientHandler();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return _tracer.ChildTraceAsync($"httpclient {request.Method}", DateTimeOffset.UtcNow, span => TracingSendAsync(span, request, cancellationToken));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual async Task<HttpResponseMessage> TracingSendAsync(ISpan span, HttpRequestMessage request, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IEnumerable<string> traceIdVals = null;
 | 
				
			||||||
 | 
					            if (request.Headers.TryGetValues(prefix_spanId, out traceIdVals))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                request.Headers.Remove(prefix_spanId);
 | 
				
			||||||
 | 
					                request.Headers.TryAddWithoutValidation(prefix_spanId, span.SpanContext.SpanId);
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            span.Tags.Client().Component("HttpClient")
 | 
				
			||||||
 | 
					                .HttpMethod(request.Method.Method)
 | 
				
			||||||
 | 
					                .HttpUrl(request.RequestUri.OriginalString)
 | 
				
			||||||
 | 
					                .HttpHost(request.RequestUri.Host)
 | 
				
			||||||
 | 
					                .HttpPath(request.RequestUri.PathAndQuery)
 | 
				
			||||||
 | 
					                .PeerAddress(request.RequestUri.OriginalString)
 | 
				
			||||||
 | 
					                .PeerHostName(request.RequestUri.Host)
 | 
				
			||||||
 | 
					                .PeerPort(request.RequestUri.Port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _tracer.Tracer.Inject(span.SpanContext, request.Headers, (c, k, v) =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (!c.Contains(k))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    c.Add(k, v);
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            span.Log(LogField.CreateNew().ClientSend());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var responseMessage = await base.SendAsync(request, cancellationToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            span.Log(LogField.CreateNew().ClientReceive());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return responseMessage;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Threading.Tasks;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
using Ocelot.Errors;
 | 
					using Ocelot.Errors;
 | 
				
			||||||
using Ocelot.Infrastructure.RequestData;
 | 
					using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
using Ocelot.Logging;
 | 
					using Ocelot.Logging;
 | 
				
			||||||
using Ocelot.Middleware;
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Responder.Middleware
 | 
					namespace Ocelot.Responder.Middleware
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -22,7 +22,8 @@ namespace Ocelot.Responder.Middleware
 | 
				
			|||||||
            IHttpResponder responder,
 | 
					            IHttpResponder responder,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IRequestScopedDataRepository requestScopedDataRepository, 
 | 
					            IRequestScopedDataRepository requestScopedDataRepository, 
 | 
				
			||||||
            IErrorsToHttpStatusCodeMapper codeMapper)
 | 
					            IErrorsToHttpStatusCodeMapper codeMapper
 | 
				
			||||||
 | 
					           )
 | 
				
			||||||
            :base(requestScopedDataRepository)
 | 
					            :base(requestScopedDataRepository)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
@@ -40,7 +41,6 @@ namespace Ocelot.Responder.Middleware
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                var errors = PipelineErrors;
 | 
					                var errors = PipelineErrors;
 | 
				
			||||||
                _logger.LogError($"{PipelineErrors.Count} pipeline errors found in {MiddlewareName}. Setting error response status code");
 | 
					                _logger.LogError($"{PipelineErrors.Count} pipeline errors found in {MiddlewareName}. Setting error response status code");
 | 
				
			||||||
 | 
					 | 
				
			||||||
                SetErrorResponse(context, errors);
 | 
					                SetErrorResponse(context, errors);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,8 @@ namespace Ocelot.IntegrationTests
 | 
				
			|||||||
            services
 | 
					            services
 | 
				
			||||||
                .AddOcelot(Configuration)
 | 
					                .AddOcelot(Configuration)
 | 
				
			||||||
                .AddAdministration("/administration", "secret")
 | 
					                .AddAdministration("/administration", "secret")
 | 
				
			||||||
                .AddRafty();
 | 
					                .AddRafty()
 | 
				
			||||||
 | 
					                ;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 | 
					        public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,11 @@ namespace Ocelot.ManualTest
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            services.AddOcelot()
 | 
					            services.AddOcelot()
 | 
				
			||||||
                    .AddCacheManager(settings)
 | 
					                    .AddCacheManager(settings)
 | 
				
			||||||
 | 
					                    .AddOpenTracing(option =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        option.CollectorUrl = "http://localhost:9618";
 | 
				
			||||||
 | 
					                        option.Service = "Ocelot.ManualTest";
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
                    .AddAdministration("/administration", "secret");
 | 
					                    .AddAdministration("/administration", "secret");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,22 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "ReRoutes": [
 | 
					  "ReRoutes": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "DownstreamPathTemplate": "/api/values",
 | 
				
			||||||
 | 
					      "DownstreamScheme": "http",
 | 
				
			||||||
 | 
					      "UpstreamPathTemplate": "/api/values",
 | 
				
			||||||
 | 
					      "UpstreamHttpMethod": [ "Get" ],
 | 
				
			||||||
 | 
					      "DownstreamHostAndPorts": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "Host": "localhost",
 | 
				
			||||||
 | 
					          "Port": 5002
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "HttpHandlerOptions": {
 | 
				
			||||||
 | 
					        "AllowAutoRedirect": true,
 | 
				
			||||||
 | 
					        "UseCookieContainer": true,
 | 
				
			||||||
 | 
					        "UseTracing": true
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "DownstreamPathTemplate": "/",
 | 
					      "DownstreamPathTemplate": "/",
 | 
				
			||||||
      "DownstreamScheme": "http",
 | 
					      "DownstreamScheme": "http",
 | 
				
			||||||
@@ -282,6 +299,6 @@
 | 
				
			|||||||
  ],
 | 
					  ],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  "GlobalConfiguration": {
 | 
					  "GlobalConfiguration": {
 | 
				
			||||||
    "RequestIdKey": "OcRequestId"
 | 
					    "RequestIdKey": "ot-traceid"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -471,7 +471,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var reRouteOptions = new ReRouteOptionsBuilder()
 | 
					            var reRouteOptions = new ReRouteOptionsBuilder()
 | 
				
			||||||
                .Build();
 | 
					                .Build();
 | 
				
			||||||
            var httpHandlerOptions = new HttpHandlerOptions(true, true);
 | 
					            var httpHandlerOptions = new HttpHandlerOptions(true, true,false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.Given(x => x.GivenTheConfigIs(new FileConfiguration
 | 
					            this.Given(x => x.GivenTheConfigIs(new FileConfiguration
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
        public void should_create_options_with_useCookie_and_allowAutoRedirect_true_as_default()
 | 
					        public void should_create_options_with_useCookie_and_allowAutoRedirect_true_as_default()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var fileReRoute = new FileReRoute();
 | 
					            var fileReRoute = new FileReRoute();
 | 
				
			||||||
            var expectedOptions = new HttpHandlerOptions(true, true);
 | 
					            var expectedOptions = new HttpHandlerOptions(true, true, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.Given(x => GivenTheFollowing(fileReRoute))
 | 
					            this.Given(x => GivenTheFollowing(fileReRoute))
 | 
				
			||||||
                .When(x => WhenICreateHttpHandlerOptions())
 | 
					                .When(x => WhenICreateHttpHandlerOptions())
 | 
				
			||||||
@@ -39,11 +39,12 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
                HttpHandlerOptions = new FileHttpHandlerOptions
 | 
					                HttpHandlerOptions = new FileHttpHandlerOptions
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    AllowAutoRedirect = false,
 | 
					                    AllowAutoRedirect = false,
 | 
				
			||||||
                    UseCookieContainer = false
 | 
					                    UseCookieContainer = false,
 | 
				
			||||||
 | 
					                    UseTracing = false
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var expectedOptions = new HttpHandlerOptions(false, false);
 | 
					            var expectedOptions = new HttpHandlerOptions(false, false, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.Given(x => GivenTheFollowing(fileReRoute))
 | 
					            this.Given(x => GivenTheFollowing(fileReRoute))
 | 
				
			||||||
                .When(x => WhenICreateHttpHandlerOptions())
 | 
					                .When(x => WhenICreateHttpHandlerOptions())
 | 
				
			||||||
@@ -66,6 +67,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
            _httpHandlerOptions.ShouldNotBeNull();
 | 
					            _httpHandlerOptions.ShouldNotBeNull();
 | 
				
			||||||
            _httpHandlerOptions.AllowAutoRedirect.ShouldBe(options.AllowAutoRedirect);
 | 
					            _httpHandlerOptions.AllowAutoRedirect.ShouldBe(options.AllowAutoRedirect);
 | 
				
			||||||
            _httpHandlerOptions.UseCookieContainer.ShouldBe(options.UseCookieContainer);
 | 
					            _httpHandlerOptions.UseCookieContainer.ShouldBe(options.UseCookieContainer);
 | 
				
			||||||
 | 
					            _httpHandlerOptions.UseTracing.ShouldBe(options.UseTracing);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,4 @@
 | 
				
			|||||||
using System;
 | 
					using CacheManager.Core;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Net.Http;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using CacheManager.Core;
 | 
					 | 
				
			||||||
using Microsoft.AspNetCore.Hosting;
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
using Microsoft.AspNetCore.Hosting.Internal;
 | 
					using Microsoft.AspNetCore.Hosting.Internal;
 | 
				
			||||||
using Microsoft.Extensions.Configuration;
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
@@ -13,8 +8,11 @@ using Ocelot.Configuration;
 | 
				
			|||||||
using Ocelot.Configuration.File;
 | 
					using Ocelot.Configuration.File;
 | 
				
			||||||
using Ocelot.Configuration.Setter;
 | 
					using Ocelot.Configuration.Setter;
 | 
				
			||||||
using Ocelot.DependencyInjection;
 | 
					using Ocelot.DependencyInjection;
 | 
				
			||||||
using Ocelot.Logging;
 | 
					using Ocelot.Requester;
 | 
				
			||||||
using Shouldly;
 | 
					using Shouldly;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
using TestStack.BDDfy;
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
using Xunit;
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,6 +94,16 @@ namespace Ocelot.UnitTests.DependencyInjection
 | 
				
			|||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_set_up_tracing()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x => WhenISetUpOcelotServices())
 | 
				
			||||||
 | 
					                .When(x => WhenISetUpOpentracing())
 | 
				
			||||||
 | 
					                .When(x => WhenIAccessOcelotHttpTracingHandler())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void should_set_up_without_passing_in_config()
 | 
					        public void should_set_up_without_passing_in_config()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -193,6 +201,24 @@ namespace Ocelot.UnitTests.DependencyInjection
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenISetUpOpentracing()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _ocelotBuilder.AddOpenTracing(
 | 
				
			||||||
 | 
					                    option =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        option.CollectorUrl = "http://localhost:9618";
 | 
				
			||||||
 | 
					                        option.Service = "Ocelot.ManualTest";
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					               );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception e)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _ex = e;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void WhenIAccessLoggerFactory()
 | 
					        private void WhenIAccessLoggerFactory()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
@@ -205,6 +231,18 @@ namespace Ocelot.UnitTests.DependencyInjection
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenIAccessOcelotHttpTracingHandler()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var tracingHandler = _serviceProvider.GetService<OcelotHttpTracingHandler>();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception e)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _ex = e;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void WhenIValidateScopes()
 | 
					        private void WhenIValidateScopes()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
    using Ocelot.Requester.QoS;
 | 
					    using Ocelot.Requester.QoS;
 | 
				
			||||||
    using Ocelot.Configuration;
 | 
					    using Ocelot.Configuration;
 | 
				
			||||||
    using Microsoft.AspNetCore.Builder;
 | 
					    using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					    using Ocelot.Errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class HttpRequestBuilderMiddlewareTests : ServerHostedMiddlewareTest
 | 
					    public class HttpRequestBuilderMiddlewareTests : ServerHostedMiddlewareTest
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -51,18 +52,39 @@
 | 
				
			|||||||
                new ReRouteBuilder()
 | 
					                new ReRouteBuilder()
 | 
				
			||||||
                    .WithRequestIdKey("LSRequestId")
 | 
					                    .WithRequestIdKey("LSRequestId")
 | 
				
			||||||
                    .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
					                    .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
				
			||||||
                    .WithHttpHandlerOptions(new HttpHandlerOptions(true, true))
 | 
					                    .WithHttpHandlerOptions(new HttpHandlerOptions(true, true,false))
 | 
				
			||||||
                    .Build());
 | 
					                    .Build());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
 | 
					            this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
 | 
				
			||||||
                .And(x => x.GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(new NoQoSProvider())))
 | 
					                .And(x => x.GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(new NoQoSProvider())))
 | 
				
			||||||
                .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
					                .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
				
			||||||
                .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false)))
 | 
					                .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false,false)))
 | 
				
			||||||
                .When(x => x.WhenICallTheMiddleware())
 | 
					                .When(x => x.WhenICallTheMiddleware())
 | 
				
			||||||
                .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
 | 
					                .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
 | 
				
			||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_call_scoped_data_repository_QosProviderError()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
 | 
				
			||||||
 | 
					                new ReRouteBuilder()
 | 
				
			||||||
 | 
					                    .WithRequestIdKey("LSRequestId")
 | 
				
			||||||
 | 
					                    .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
				
			||||||
 | 
					                    .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
 | 
				
			||||||
 | 
					                    .Build());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
 | 
				
			||||||
 | 
					                .And(x => x.GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
 | 
				
			||||||
 | 
					                .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
				
			||||||
 | 
					                .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false, false)))
 | 
				
			||||||
 | 
					                .When(x => x.WhenICallTheMiddleware())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenTheScopedDataRepositoryQosProviderError())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
 | 
					        protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
 | 
					            services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
 | 
				
			||||||
@@ -109,7 +131,9 @@
 | 
				
			|||||||
                                    It.IsAny<bool>(),
 | 
					                                    It.IsAny<bool>(),
 | 
				
			||||||
                                    It.IsAny<IQoSProvider>(),
 | 
					                                    It.IsAny<IQoSProvider>(),
 | 
				
			||||||
                                    It.IsAny<bool>(),
 | 
					                                    It.IsAny<bool>(),
 | 
				
			||||||
                                    It.IsAny<bool>()))
 | 
					                                    It.IsAny<bool>(),
 | 
				
			||||||
 | 
					                                    It.IsAny<bool>()
 | 
				
			||||||
 | 
					                                    ))
 | 
				
			||||||
                .ReturnsAsync(_request);
 | 
					                .ReturnsAsync(_request);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -118,5 +142,11 @@
 | 
				
			|||||||
            _scopedRepository
 | 
					            _scopedRepository
 | 
				
			||||||
                .Verify(x => x.Add("Request", _request.Data), Times.Once());
 | 
					                .Verify(x => x.Add("Request", _request.Data), Times.Once());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheScopedDataRepositoryQosProviderError()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _scopedRepository
 | 
				
			||||||
 | 
					                .Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
        private readonly HttpRequestMessage _requestMessage;
 | 
					        private readonly HttpRequestMessage _requestMessage;
 | 
				
			||||||
        private readonly bool _useCookieContainer;
 | 
					        private readonly bool _useCookieContainer;
 | 
				
			||||||
        private readonly bool _allowAutoRedirect;
 | 
					        private readonly bool _allowAutoRedirect;
 | 
				
			||||||
 | 
					        private readonly bool _useTracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private Response<Ocelot.Request.Request> _response;
 | 
					        private Response<Ocelot.Request.Request> _response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,7 +28,7 @@
 | 
				
			|||||||
            _qoSProvider = new NoQoSProvider();
 | 
					            _qoSProvider = new NoQoSProvider();
 | 
				
			||||||
            _useCookieContainer = false;
 | 
					            _useCookieContainer = false;
 | 
				
			||||||
            _allowAutoRedirect = false;
 | 
					            _allowAutoRedirect = false;
 | 
				
			||||||
 | 
					            _useTracing = false;
 | 
				
			||||||
            _requestMessage = new HttpRequestMessage();
 | 
					            _requestMessage = new HttpRequestMessage();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,6 +40,7 @@
 | 
				
			|||||||
                .Then(x => x.ThenTheRequestContainsTheIsQos())
 | 
					                .Then(x => x.ThenTheRequestContainsTheIsQos())
 | 
				
			||||||
                .Then(x => x.ThenTheRequestContainsTheQosProvider())
 | 
					                .Then(x => x.ThenTheRequestContainsTheQosProvider())
 | 
				
			||||||
                .Then(x => x.ThenTheRequestContainsUseCookieContainer())
 | 
					                .Then(x => x.ThenTheRequestContainsUseCookieContainer())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenTheRequestContainsUseTracing())
 | 
				
			||||||
                .Then(x => x.ThenTheRequestContainsAllowAutoRedirect())
 | 
					                .Then(x => x.ThenTheRequestContainsAllowAutoRedirect())
 | 
				
			||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -46,7 +48,7 @@
 | 
				
			|||||||
        private void WhenIBuildARequest()
 | 
					        private void WhenIBuildARequest()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _response = _requestCreator.Build(_requestMessage,
 | 
					            _response = _requestCreator.Build(_requestMessage,
 | 
				
			||||||
                    _isQos, _qoSProvider, _useCookieContainer, _allowAutoRedirect)
 | 
					                    _isQos, _qoSProvider, _useCookieContainer, _allowAutoRedirect, _useTracing)
 | 
				
			||||||
                .GetAwaiter()
 | 
					                .GetAwaiter()
 | 
				
			||||||
                .GetResult();
 | 
					                .GetResult();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -71,6 +73,11 @@
 | 
				
			|||||||
            _response.Data.UseCookieContainer.ShouldBe(_useCookieContainer);
 | 
					            _response.Data.UseCookieContainer.ShouldBe(_useCookieContainer);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheRequestContainsUseTracing()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _response.Data.IsTracing.ShouldBe(_useTracing);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenTheRequestContainsAllowAutoRedirect()
 | 
					        private void ThenTheRequestContainsAllowAutoRedirect()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _response.Data.AllowAutoRedirect.ShouldBe(_allowAutoRedirect);
 | 
					            _response.Data.AllowAutoRedirect.ShouldBe(_allowAutoRedirect);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using Moq;
 | 
				
			||||||
 | 
					using Ocelot.Logging;
 | 
				
			||||||
 | 
					using Ocelot.Requester;
 | 
				
			||||||
 | 
					using Ocelot.Requester.QoS;
 | 
				
			||||||
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.UnitTests.Requester
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class HttpClientHttpRequesterTest
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly Mock<IHttpClientCache> _cacheHandlers;
 | 
				
			||||||
 | 
					        private Mock<IServiceProvider> _serviceProvider;
 | 
				
			||||||
 | 
					        private Response<HttpResponseMessage> _response;
 | 
				
			||||||
 | 
					        private readonly HttpClientHttpRequester _httpClientRequester;
 | 
				
			||||||
 | 
					        private Ocelot.Request.Request _request;
 | 
				
			||||||
 | 
					        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
				
			||||||
 | 
					        private Mock<IOcelotLogger> _logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public HttpClientHttpRequesterTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _serviceProvider = new Mock<IServiceProvider>();
 | 
				
			||||||
 | 
					            _logger = new Mock<IOcelotLogger>();
 | 
				
			||||||
 | 
					            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
				
			||||||
 | 
					            _loggerFactory
 | 
				
			||||||
 | 
					                .Setup(x => x.CreateLogger<HttpClientHttpRequester>())
 | 
				
			||||||
 | 
					                .Returns(_logger.Object);
 | 
				
			||||||
 | 
					            _cacheHandlers = new Mock<IHttpClientCache>();
 | 
				
			||||||
 | 
					            _httpClientRequester = new HttpClientHttpRequester(_loggerFactory.Object, _cacheHandlers.Object, _serviceProvider.Object);            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_call_request_correctly()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x=>x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage() {  RequestUri = new Uri("http://www.bbc.co.uk") }, false, new NoQoSProvider(), false, false, false)))
 | 
				
			||||||
 | 
					                .When(x=>x.WhenIGetResponse())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenTheResponseIsCalledCorrectly())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_call_request_UnableToCompleteRequest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") }, false, new NoQoSProvider(), false, false, false)))
 | 
				
			||||||
 | 
					                .When(x => x.WhenIGetResponse())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenTheResponseIsCalledError())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenTheRequestIs(Ocelot.Request.Request request)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _request = request;            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenIGetResponse()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _response = _httpClientRequester.GetResponse(_request).Result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheResponseIsCalledCorrectly()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Assert.True(_response.IsError == false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheResponseIsCalledError()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Assert.True(_response.IsError == true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }  
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -28,7 +28,7 @@
 | 
				
			|||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void should_call_scoped_data_repository_correctly()
 | 
					        public void should_call_scoped_data_repository_correctly()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),true, new NoQoSProvider(), false, false)))
 | 
					            this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),true, new NoQoSProvider(), false, false,false)))
 | 
				
			||||||
                .And(x => x.GivenTheRequesterReturns(new HttpResponseMessage()))
 | 
					                .And(x => x.GivenTheRequesterReturns(new HttpResponseMessage()))
 | 
				
			||||||
                .And(x => x.GivenTheScopedRepoReturns())
 | 
					                .And(x => x.GivenTheScopedRepoReturns())
 | 
				
			||||||
                .When(x => x.WhenICallTheMiddleware())
 | 
					                .When(x => x.WhenICallTheMiddleware())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,14 @@
 | 
				
			|||||||
namespace Ocelot.UnitTests.Responder
 | 
					namespace Ocelot.UnitTests.Responder
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    using System.Collections.Generic;
 | 
				
			||||||
    using System.Net.Http;
 | 
					    using System.Net.Http;
 | 
				
			||||||
    using Microsoft.AspNetCore.Builder;
 | 
					    using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
    using Microsoft.Extensions.DependencyInjection;
 | 
					    using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
    using Moq;
 | 
					    using Moq;
 | 
				
			||||||
 | 
					    using Ocelot.DownstreamRouteFinder.Finder;
 | 
				
			||||||
 | 
					    using Ocelot.Errors;
 | 
				
			||||||
    using Ocelot.Logging;
 | 
					    using Ocelot.Logging;
 | 
				
			||||||
 | 
					    using Ocelot.Requester;
 | 
				
			||||||
    using Ocelot.Responder;
 | 
					    using Ocelot.Responder;
 | 
				
			||||||
    using Ocelot.Responder.Middleware;
 | 
					    using Ocelot.Responder.Middleware;
 | 
				
			||||||
    using Ocelot.Responses;
 | 
					    using Ocelot.Responses;
 | 
				
			||||||
@@ -35,6 +39,17 @@
 | 
				
			|||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_return_any_errors()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage()))
 | 
				
			||||||
 | 
					                .And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError()))
 | 
				
			||||||
 | 
					                .When(x => x.WhenICallTheMiddleware())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenThereAreNoErrors())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
 | 
					        protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
 | 
					            services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
 | 
				
			||||||
@@ -68,5 +83,14 @@
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            //todo a better assert?
 | 
					            //todo a better assert?
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenThereArePipelineErrors(Error error)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ScopedRepository
 | 
				
			||||||
 | 
					                .Setup(x => x.Get<bool>("OcelotMiddlewareError"))
 | 
				
			||||||
 | 
					                .Returns(new OkResponse<bool>(true));
 | 
				
			||||||
 | 
					            ScopedRepository.Setup(x => x.Get<List<Error>>("OcelotMiddlewareErrors"))
 | 
				
			||||||
 | 
					                .Returns(new OkResponse<List<Error>>(new List<Error>() { error }));
 | 
				
			||||||
 | 
					        }  
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user