mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 20:10:50 +08:00 
			
		
		
		
	Merge branch 'release/5.5.0'
This commit is contained in:
		@@ -12,20 +12,19 @@ namespace Ocelot.Authentication.Middleware
 | 
				
			|||||||
    public class AuthenticationMiddleware : OcelotMiddleware
 | 
					    public class AuthenticationMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public AuthenticationMiddleware(OcelotRequestDelegate next,
 | 
					        public AuthenticationMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory)
 | 
					            IOcelotLoggerFactory loggerFactory)
 | 
				
			||||||
 | 
					            : base(loggerFactory.CreateLogger<AuthenticationMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<AuthenticationMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (IsAuthenticatedRoute(context.DownstreamReRoute))
 | 
					            if (IsAuthenticatedRoute(context.DownstreamReRoute))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"{context.HttpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
 | 
					                Logger.LogInformation($"{context.HttpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
 | 
					                var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
@@ -33,25 +32,22 @@ namespace Ocelot.Authentication.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (context.HttpContext.User.Identity.IsAuthenticated)
 | 
					                if (context.HttpContext.User.Identity.IsAuthenticated)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug($"Client has been authenticated for {context.HttpContext.Request.Path}");
 | 
					                    Logger.LogInformation($"Client has been authenticated for {context.HttpContext.Request.Path}");
 | 
				
			||||||
                    await _next.Invoke(context);
 | 
					                    await _next.Invoke(context);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var error = new List<Error>
 | 
					                    var error = new UnauthenticatedError(
 | 
				
			||||||
                    {
 | 
					                        $"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated");
 | 
				
			||||||
                        new UnauthenticatedError(
 | 
					 | 
				
			||||||
                            $"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated")
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    _logger.LogError($"Client has NOT been authenticated for {context.HttpContext.Request.Path} and pipeline error set. {error.ToErrorString()}");
 | 
					                    Logger.LogWarning($"Client has NOT been authenticated for {context.HttpContext.Request.Path} and pipeline error set. {error}");
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    SetPipelineError(context, error);
 | 
					                    SetPipelineError(context, error);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogTrace($"No authentication needed for {context.HttpContext.Request.Path}");
 | 
					                Logger.LogInformation($"No authentication needed for {context.HttpContext.Request.Path}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                await _next.Invoke(context);
 | 
					                await _next.Invoke(context);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Security.Claims;
 | 
					using System.Security.Claims;
 | 
				
			||||||
using Ocelot.Errors;
 | 
					 | 
				
			||||||
using Ocelot.Responses;
 | 
					using Ocelot.Responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Authorisation
 | 
					namespace Ocelot.Authorisation
 | 
				
			||||||
@@ -32,19 +31,13 @@ namespace Ocelot.Authorisation
 | 
				
			|||||||
                    var authorised = values.Data.Contains(required.Value);
 | 
					                    var authorised = values.Data.Contains(required.Value);
 | 
				
			||||||
                    if (!authorised)
 | 
					                    if (!authorised)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        return new ErrorResponse<bool>(new List<Error>
 | 
					                        return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
 | 
				
			||||||
                        {
 | 
					                                $"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}"));
 | 
				
			||||||
                            new ClaimValueNotAuthorisedError(
 | 
					 | 
				
			||||||
                                $"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}")
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return new ErrorResponse<bool>(new List<Error>
 | 
					                    return new ErrorResponse<bool>(new UserDoesNotHaveClaimError($"user does not have claim {required.Key}"));
 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            new UserDoesNotHaveClaimError($"user does not have claim {required.Key}")
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,30 +13,29 @@
 | 
				
			|||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IClaimsAuthoriser _claimsAuthoriser;
 | 
					        private readonly IClaimsAuthoriser _claimsAuthoriser;
 | 
				
			||||||
        private readonly IScopesAuthoriser _scopesAuthoriser;
 | 
					        private readonly IScopesAuthoriser _scopesAuthoriser;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public AuthorisationMiddleware(OcelotRequestDelegate next,
 | 
					        public AuthorisationMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IClaimsAuthoriser claimsAuthoriser,
 | 
					            IClaimsAuthoriser claimsAuthoriser,
 | 
				
			||||||
            IScopesAuthoriser scopesAuthoriser,
 | 
					            IScopesAuthoriser scopesAuthoriser,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory)
 | 
					            IOcelotLoggerFactory loggerFactory)
 | 
				
			||||||
 | 
					            :base(loggerFactory.CreateLogger<AuthorisationMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _claimsAuthoriser = claimsAuthoriser;
 | 
					            _claimsAuthoriser = claimsAuthoriser;
 | 
				
			||||||
            _scopesAuthoriser = scopesAuthoriser;
 | 
					            _scopesAuthoriser = scopesAuthoriser;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (IsAuthenticatedRoute(context.DownstreamReRoute))
 | 
					            if (IsAuthenticatedRoute(context.DownstreamReRoute))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("route is authenticated scopes must be checked");
 | 
					                Logger.LogInformation("route is authenticated scopes must be checked");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes);
 | 
					                var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (authorised.IsError)
 | 
					                if (authorised.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("error authorising user scopes");
 | 
					                    Logger.LogWarning("error authorising user scopes");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, authorised.Errors);
 | 
					                    SetPipelineError(context, authorised.Errors);
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
@@ -44,29 +43,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (IsAuthorised(authorised))
 | 
					                if (IsAuthorised(authorised))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("user scopes is authorised calling next authorisation checks");
 | 
					                    Logger.LogInformation("user scopes is authorised calling next authorisation checks");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("user scopes is not authorised setting pipeline error");
 | 
					                    Logger.LogWarning("user scopes is not authorised setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, new List<Error>
 | 
					                    SetPipelineError(context, new UnauthorisedError(
 | 
				
			||||||
                    {
 | 
					                            $"{context.HttpContext.User.Identity.Name} unable to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}"));
 | 
				
			||||||
                        new UnauthorisedError(
 | 
					 | 
				
			||||||
                            $"{context.HttpContext.User.Identity.Name} unable to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}")
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (IsAuthorisedRoute(context.DownstreamReRoute))
 | 
					            if (IsAuthorisedRoute(context.DownstreamReRoute))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("route is authorised");
 | 
					                Logger.LogInformation("route is authorised");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement);
 | 
					                var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (authorised.IsError)
 | 
					                if (authorised.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug($"Error whilst authorising {context.HttpContext.User.Identity.Name} for {context.HttpContext.User.Identity.Name}. Setting pipeline error");
 | 
					                    Logger.LogWarning($"Error whilst authorising {context.HttpContext.User.Identity.Name}. Setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, authorised.Errors);
 | 
					                    SetPipelineError(context, authorised.Errors);
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
@@ -74,22 +70,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (IsAuthorised(authorised))
 | 
					                if (IsAuthorised(authorised))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug($"{context.HttpContext.User.Identity.Name} has succesfully been authorised for {context.DownstreamReRoute.UpstreamPathTemplate.Value}. Calling next middleware");
 | 
					                    Logger.LogInformation($"{context.HttpContext.User.Identity.Name} has succesfully been authorised for {context.DownstreamReRoute.UpstreamPathTemplate.Value}.");
 | 
				
			||||||
                    await _next.Invoke(context);
 | 
					                    await _next.Invoke(context);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}. Setting pipeline error");
 | 
					                    Logger.LogWarning($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}. Setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, new List<Error>
 | 
					                    SetPipelineError(context, new UnauthorisedError($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}"));
 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        new UnauthorisedError($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}")
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
 | 
					                Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
 | 
				
			||||||
                await _next.Invoke(context);
 | 
					                await _next.Invoke(context);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
using IdentityModel;
 | 
					using IdentityModel;
 | 
				
			||||||
using Ocelot.Errors;
 | 
					 | 
				
			||||||
using Ocelot.Responses;
 | 
					using Ocelot.Responses;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Security.Claims;
 | 
					using System.Security.Claims;
 | 
				
			||||||
@@ -38,11 +37,8 @@ namespace Ocelot.Authorisation
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (matchesScopes.Count == 0)
 | 
					            if (matchesScopes.Count == 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse<bool>(new List<Error>
 | 
					                return new ErrorResponse<bool>(
 | 
				
			||||||
                {
 | 
					                    new ScopeNotAuthorisedError($"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'"));
 | 
				
			||||||
                     new ScopeNotAuthorisedError(
 | 
					 | 
				
			||||||
                         $"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'")
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new OkResponse<bool>(true);
 | 
					            return new OkResponse<bool>(true);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ namespace Ocelot.Cache.Middleware
 | 
				
			|||||||
    public class OutputCacheMiddleware : OcelotMiddleware
 | 
					    public class OutputCacheMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly IOcelotCache<CachedResponse> _outputCache;
 | 
					        private readonly IOcelotCache<CachedResponse> _outputCache;
 | 
				
			||||||
        private readonly IRegionCreator _regionCreator;
 | 
					        private readonly IRegionCreator _regionCreator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -22,10 +21,10 @@ namespace Ocelot.Cache.Middleware
 | 
				
			|||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IOcelotCache<CachedResponse> outputCache,
 | 
					            IOcelotCache<CachedResponse> outputCache,
 | 
				
			||||||
            IRegionCreator regionCreator)
 | 
					            IRegionCreator regionCreator)
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _outputCache = outputCache;
 | 
					            _outputCache = outputCache;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
 | 
					 | 
				
			||||||
            _regionCreator = regionCreator;
 | 
					            _regionCreator = regionCreator;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,29 +38,29 @@ namespace Ocelot.Cache.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var downstreamUrlKey = $"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}";
 | 
					            var downstreamUrlKey = $"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey);
 | 
					            Logger.LogDebug($"Started checking cache for {downstreamUrlKey}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region);
 | 
					            var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (cached != null)
 | 
					            if (cached != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("cache entry exists for {downstreamUrlKey}", downstreamUrlKey);
 | 
					                Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var response = CreateHttpResponseMessage(cached);
 | 
					                var response = CreateHttpResponseMessage(cached);
 | 
				
			||||||
                SetHttpResponseMessageThisRequest(context, response);
 | 
					                SetHttpResponseMessageThisRequest(context, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _logger.LogDebug("finished returned cached response for {downstreamUrlKey}", downstreamUrlKey);
 | 
					                Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("no resonse cached for {downstreamUrlKey}", downstreamUrlKey);
 | 
					            Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await _next.Invoke(context);
 | 
					            await _next.Invoke(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (context.IsError)
 | 
					            if (context.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey);
 | 
					                Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -70,7 +69,7 @@ namespace Ocelot.Cache.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            _outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region);
 | 
					            _outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
 | 
					            Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void SetHttpResponseMessageThisRequest(DownstreamContext context, HttpResponseMessage response)
 | 
					        private void SetHttpResponseMessageThisRequest(DownstreamContext context, HttpResponseMessage response)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,28 +12,27 @@ namespace Ocelot.Claims.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IAddClaimsToRequest _addClaimsToRequest;
 | 
					        private readonly IAddClaimsToRequest _addClaimsToRequest;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ClaimsBuilderMiddleware(OcelotRequestDelegate next, 
 | 
					        public ClaimsBuilderMiddleware(OcelotRequestDelegate next, 
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IAddClaimsToRequest addClaimsToRequest) 
 | 
					            IAddClaimsToRequest addClaimsToRequest) 
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<ClaimsBuilderMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _addClaimsToRequest = addClaimsToRequest;
 | 
					            _addClaimsToRequest = addClaimsToRequest;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<ClaimsBuilderMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (context.DownstreamReRoute.ClaimsToClaims.Any())
 | 
					            if (context.DownstreamReRoute.ClaimsToClaims.Any())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("this route has instructions to convert claims to other claims");
 | 
					                Logger.LogDebug("this route has instructions to convert claims to other claims");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var result = _addClaimsToRequest.SetClaimsOnContext(context.DownstreamReRoute.ClaimsToClaims, context.HttpContext);
 | 
					                var result = _addClaimsToRequest.SetClaimsOnContext(context.DownstreamReRoute.ClaimsToClaims, context.HttpContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (result.IsError)
 | 
					                if (result.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("error converting claims to other claims, setting pipeline error");
 | 
					                    Logger.LogDebug("error converting claims to other claims, setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, result.Errors);
 | 
					                    SetPipelineError(context, result.Errors);
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,7 @@ namespace Ocelot.Configuration.Creator
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (claimToThing.IsError)
 | 
					                if (claimToThing.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("ClaimsToThingCreator.BuildAddThingsToRequest",
 | 
					                    _logger.LogDebug($"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
 | 
				
			||||||
                        $"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ namespace Ocelot.Configuration.Creator
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogError($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
 | 
					                    _logger.LogWarning($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,7 +50,7 @@ namespace Ocelot.Configuration.Creator
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        _logger.LogError($"Unable to add DownstreamHeaderTransform {input.Key}: {input.Value}");
 | 
					                        _logger.LogWarning($"Unable to add DownstreamHeaderTransform {input.Key}: {input.Value}");
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,22 +20,14 @@ namespace Ocelot.Configuration.Parser
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (instructions.Length <= 1)
 | 
					                if (instructions.Length <= 1)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return new ErrorResponse<ClaimToThing>(
 | 
					                    return new ErrorResponse<ClaimToThing>(new NoInstructionsError(SplitToken));
 | 
				
			||||||
                        new List<Error>
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        new NoInstructionsError(SplitToken)
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var claimMatch = _claimRegex.IsMatch(instructions[0]);
 | 
					                var claimMatch = _claimRegex.IsMatch(instructions[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!claimMatch)
 | 
					                if (!claimMatch)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return new ErrorResponse<ClaimToThing>(
 | 
					                    return new ErrorResponse<ClaimToThing>(new InstructionNotForClaimsError());
 | 
				
			||||||
                        new List<Error>
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            new InstructionNotForClaimsError()
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var newKey = GetIndexValue(instructions[0]);
 | 
					                var newKey = GetIndexValue(instructions[0]);
 | 
				
			||||||
@@ -53,11 +45,7 @@ namespace Ocelot.Configuration.Parser
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse<ClaimToThing>(
 | 
					                return new ErrorResponse<ClaimToThing>(new ParsingConfigurationHeaderError(exception));
 | 
				
			||||||
                    new List<Error>
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        new ParsingConfigurationHeaderError(exception)
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,13 +45,13 @@ namespace Ocelot.Configuration.Repository
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        private async Task Poll()
 | 
					        private async Task Poll()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogDebug("Started polling consul");
 | 
					            _logger.LogInformation("Started polling consul");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var fileConfig = await _repo.Get();
 | 
					            var fileConfig = await _repo.Get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(fileConfig.IsError)
 | 
					            if(fileConfig.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"error geting file config, errors are {string.Join(",", fileConfig.Errors.Select(x => x.Message))}");
 | 
					                _logger.LogWarning($"error geting file config, errors are {string.Join(",", fileConfig.Errors.Select(x => x.Message))}");
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -63,7 +63,7 @@ namespace Ocelot.Configuration.Repository
 | 
				
			|||||||
                _previousAsJson = asJson;
 | 
					                _previousAsJson = asJson;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("Finished polling consul");
 | 
					            _logger.LogInformation("Finished polling consul");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,8 +17,8 @@ namespace Ocelot.Configuration.Validator
 | 
				
			|||||||
            Errors = errors;
 | 
					            Errors = errors;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsError { get; private set; }
 | 
					        public bool IsError { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public List<Error> Errors { get; private set; } 
 | 
					        public List<Error> Errors { get; } 
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,10 +44,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
 | 
				
			|||||||
                return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
 | 
					                return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new ErrorResponse<DownstreamRoute>(new List<Error>
 | 
					            return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(path, httpMethod));
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                new UnableToFindDownstreamRouteError()
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
 | 
					        private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,8 @@ namespace Ocelot.DownstreamRouteFinder.Finder
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class UnableToFindDownstreamRouteError : Error
 | 
					    public class UnableToFindDownstreamRouteError : Error
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public UnableToFindDownstreamRouteError() : base("UnableToFindDownstreamRouteError", OcelotErrorCode.UnableToFindDownstreamRouteError)
 | 
					        public UnableToFindDownstreamRouteError(string path, string httpVerb) 
 | 
				
			||||||
 | 
					            : base($"Unable to find downstream route for path: {path}, verb: {httpVerb}", OcelotErrorCode.UnableToFindDownstreamRouteError)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
using Ocelot.Configuration;
 | 
					using Ocelot.Configuration;
 | 
				
			||||||
using Ocelot.Configuration.Provider;
 | 
					using Ocelot.Configuration.Provider;
 | 
				
			||||||
using Ocelot.DownstreamRouteFinder.Finder;
 | 
					using Ocelot.DownstreamRouteFinder.Finder;
 | 
				
			||||||
@@ -13,7 +14,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IDownstreamRouteFinder _downstreamRouteFinder;
 | 
					        private readonly IDownstreamRouteFinder _downstreamRouteFinder;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly IOcelotConfigurationProvider _configProvider;
 | 
					        private readonly IOcelotConfigurationProvider _configProvider;
 | 
				
			||||||
        private readonly IMultiplexer _multiplexer;
 | 
					        private readonly IMultiplexer _multiplexer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -22,12 +22,12 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
				
			|||||||
            IDownstreamRouteFinder downstreamRouteFinder,
 | 
					            IDownstreamRouteFinder downstreamRouteFinder,
 | 
				
			||||||
            IOcelotConfigurationProvider configProvider,
 | 
					            IOcelotConfigurationProvider configProvider,
 | 
				
			||||||
            IMultiplexer multiplexer)
 | 
					            IMultiplexer multiplexer)
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _configProvider = configProvider;
 | 
					            _configProvider = configProvider;
 | 
				
			||||||
            _multiplexer = multiplexer;
 | 
					            _multiplexer = multiplexer;
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _downstreamRouteFinder = downstreamRouteFinder;
 | 
					            _downstreamRouteFinder = downstreamRouteFinder;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
@@ -40,27 +40,27 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (configuration.IsError)
 | 
					            if (configuration.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogError($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
 | 
					                Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
 | 
				
			||||||
                SetPipelineError(context, configuration.Errors);
 | 
					                SetPipelineError(context, configuration.Errors);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            context.ServiceProviderConfiguration = configuration.Data.ServiceProviderConfiguration;
 | 
					            context.ServiceProviderConfiguration = configuration.Data.ServiceProviderConfiguration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
 | 
					            Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.HttpContext.Request.Method, configuration.Data, upstreamHost);
 | 
					            var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.HttpContext.Request.Method, configuration.Data, upstreamHost);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (downstreamRoute.IsError)
 | 
					            if (downstreamRoute.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogError($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
 | 
					                Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SetPipelineError(context, downstreamRoute.Errors);
 | 
					                SetPipelineError(context, downstreamRoute.Errors);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }            
 | 
					            }            
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // todo - put this back in
 | 
					            var downstreamPathTemplates = string.Join(", ", downstreamRoute.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));
 | 
				
			||||||
            //// _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate);
 | 
					            Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;
 | 
					            context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
using Ocelot.Responses;
 | 
					 | 
				
			||||||
using Ocelot.Values;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Ocelot.DownstreamUrlCreator
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public interface IUrlBuilder
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Response<DownstreamUrl> Build(string downstreamPath, string downstreamScheme, ServiceHostAndPort downstreamHostAndPort);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
@@ -16,15 +16,14 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IDownstreamPathPlaceholderReplacer _replacer;
 | 
					        private readonly IDownstreamPathPlaceholderReplacer _replacer;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next,
 | 
					        public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IDownstreamPathPlaceholderReplacer replacer)
 | 
					            IDownstreamPathPlaceholderReplacer replacer)
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _replacer = replacer;
 | 
					            _replacer = replacer;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
@@ -34,7 +33,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (dsPath.IsError)
 | 
					            if (dsPath.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
 | 
					                Logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SetPipelineError(context, dsPath.Errors);
 | 
					                SetPipelineError(context, dsPath.Errors);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
@@ -53,7 +52,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
 | 
				
			|||||||
                context.DownstreamRequest.AbsolutePath = dsPath.Data.Value;
 | 
					                context.DownstreamRequest.AbsolutePath = dsPath.Data.Value;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("downstream url is {context.DownstreamRequest}", context.DownstreamRequest);
 | 
					            Logger.LogDebug($"Downstream url is {context.DownstreamRequest}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await _next.Invoke(context);
 | 
					            await _next.Invoke(context);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,47 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using Ocelot.Errors;
 | 
					 | 
				
			||||||
using Ocelot.Responses;
 | 
					 | 
				
			||||||
using Ocelot.Values;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Ocelot.DownstreamUrlCreator
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public class UrlBuilder : IUrlBuilder
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public Response<DownstreamUrl> Build(string downstreamPath, string downstreamScheme, ServiceHostAndPort downstreamHostAndPort)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (string.IsNullOrEmpty(downstreamPath))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return new ErrorResponse<DownstreamUrl>(new List<Error> {new DownstreamPathNullOrEmptyError()});
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (string.IsNullOrEmpty(downstreamScheme))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamSchemeNullOrEmptyError() });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (string.IsNullOrEmpty(downstreamHostAndPort.DownstreamHost))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamHostNullOrEmptyError() });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var builder = new UriBuilder
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Host = downstreamHostAndPort.DownstreamHost,
 | 
					 | 
				
			||||||
                Path = downstreamPath,
 | 
					 | 
				
			||||||
                Scheme = downstreamScheme,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (downstreamHostAndPort.DownstreamPort > 0)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                builder.Port = downstreamHostAndPort.DownstreamPort;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            var url = builder.Uri.ToString();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return new OkResponse<DownstreamUrl>(new DownstreamUrl(url));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
@@ -18,7 +18,6 @@ namespace Ocelot.Errors.Middleware
 | 
				
			|||||||
    public class ExceptionHandlerMiddleware : OcelotMiddleware
 | 
					    public class ExceptionHandlerMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly IOcelotConfigurationProvider _provider;
 | 
					        private readonly IOcelotConfigurationProvider _provider;
 | 
				
			||||||
        private readonly IRequestScopedDataRepository _repo;
 | 
					        private readonly IRequestScopedDataRepository _repo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,11 +25,11 @@ namespace Ocelot.Errors.Middleware
 | 
				
			|||||||
            IOcelotLoggerFactory loggerFactory, 
 | 
					            IOcelotLoggerFactory loggerFactory, 
 | 
				
			||||||
            IOcelotConfigurationProvider provider, 
 | 
					            IOcelotConfigurationProvider provider, 
 | 
				
			||||||
            IRequestScopedDataRepository repo)
 | 
					            IRequestScopedDataRepository repo)
 | 
				
			||||||
 | 
					                : base(loggerFactory.CreateLogger<ExceptionHandlerMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _provider = provider;
 | 
					            _provider = provider;
 | 
				
			||||||
            _repo = repo;
 | 
					            _repo = repo;
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
@@ -39,22 +38,22 @@ namespace Ocelot.Errors.Middleware
 | 
				
			|||||||
            {               
 | 
					            {               
 | 
				
			||||||
                await TrySetGlobalRequestId(context);
 | 
					                await TrySetGlobalRequestId(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _logger.LogDebug("ocelot pipeline started");
 | 
					                Logger.LogDebug("ocelot pipeline started");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                await _next.Invoke(context);
 | 
					                await _next.Invoke(context);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception e)
 | 
					            catch (Exception e)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("error calling middleware");
 | 
					                Logger.LogDebug("error calling middleware");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var message = CreateMessage(context, e);
 | 
					                var message = CreateMessage(context, e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _logger.LogError(message, e);
 | 
					                Logger.LogError(message, e);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                SetInternalServerErrorOnResponse(context);
 | 
					                SetInternalServerErrorOnResponse(context);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("ocelot pipeline finished");
 | 
					            Logger.LogDebug("ocelot pipeline finished");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task TrySetGlobalRequestId(DownstreamContext context)
 | 
					        private async Task TrySetGlobalRequestId(DownstreamContext context)
 | 
				
			||||||
@@ -64,22 +63,19 @@ namespace Ocelot.Errors.Middleware
 | 
				
			|||||||
            //first thing is get config
 | 
					            //first thing is get config
 | 
				
			||||||
            var configuration = await _provider.Get(); 
 | 
					            var configuration = await _provider.Get(); 
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
                //if error throw to catch below..
 | 
					 | 
				
			||||||
            if(configuration.IsError)
 | 
					            if(configuration.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
 | 
					                throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                //else set the request id?
 | 
					 | 
				
			||||||
            var key = configuration.Data.RequestId;
 | 
					            var key = configuration.Data.RequestId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                StringValues upstreamRequestIds;
 | 
					            if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
 | 
				
			||||||
                if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out upstreamRequestIds))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                    //todo fix looking in both places
 | 
					 | 
				
			||||||
                context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
 | 
					                context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
 | 
				
			||||||
                    _repo.Add<string>("RequestId", context.HttpContext.TraceIdentifier);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _repo.Add("RequestId", context.HttpContext.TraceIdentifier);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void SetInternalServerErrorOnResponse(DownstreamContext context)
 | 
					        private void SetInternalServerErrorOnResponse(DownstreamContext context)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@ namespace Ocelot.Headers
 | 
				
			|||||||
                    
 | 
					                    
 | 
				
			||||||
                    if(value.IsError)
 | 
					                    if(value.IsError)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        _logger.LogError($"Unable to add header to response {add.Key}: {add.Value}");
 | 
					                        _logger.LogWarning($"Unable to add header to response {add.Key}: {add.Value}");
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,6 @@ namespace Ocelot.Headers.Middleware
 | 
				
			|||||||
    public class HttpHeadersTransformationMiddleware : OcelotMiddleware
 | 
					    public class HttpHeadersTransformationMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly IHttpContextRequestHeaderReplacer _preReplacer;
 | 
					        private readonly IHttpContextRequestHeaderReplacer _preReplacer;
 | 
				
			||||||
        private readonly IHttpResponseHeaderReplacer _postReplacer;
 | 
					        private readonly IHttpResponseHeaderReplacer _postReplacer;
 | 
				
			||||||
        private readonly IAddHeadersToResponse _addHeaders;
 | 
					        private readonly IAddHeadersToResponse _addHeaders;
 | 
				
			||||||
@@ -20,12 +19,12 @@ namespace Ocelot.Headers.Middleware
 | 
				
			|||||||
            IHttpContextRequestHeaderReplacer preReplacer,
 | 
					            IHttpContextRequestHeaderReplacer preReplacer,
 | 
				
			||||||
            IHttpResponseHeaderReplacer postReplacer,
 | 
					            IHttpResponseHeaderReplacer postReplacer,
 | 
				
			||||||
            IAddHeadersToResponse addHeaders) 
 | 
					            IAddHeadersToResponse addHeaders) 
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _addHeaders = addHeaders;
 | 
					            _addHeaders = addHeaders;
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _postReplacer = postReplacer;
 | 
					            _postReplacer = postReplacer;
 | 
				
			||||||
            _preReplacer = preReplacer;
 | 
					            _preReplacer = preReplacer;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,34 +12,33 @@ namespace Ocelot.Headers.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IAddHeadersToRequest _addHeadersToRequest;
 | 
					        private readonly IAddHeadersToRequest _addHeadersToRequest;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public HttpRequestHeadersBuilderMiddleware(OcelotRequestDelegate next,
 | 
					        public HttpRequestHeadersBuilderMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IAddHeadersToRequest addHeadersToRequest)  
 | 
					            IAddHeadersToRequest addHeadersToRequest)  
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _addHeadersToRequest = addHeadersToRequest;
 | 
					            _addHeadersToRequest = addHeadersToRequest;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (context.DownstreamReRoute.ClaimsToHeaders.Any())
 | 
					            if (context.DownstreamReRoute.ClaimsToHeaders.Any())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"{ context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
 | 
					                Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.ClaimsToHeaders, context.HttpContext.User.Claims, context.DownstreamRequest);
 | 
					                var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.ClaimsToHeaders, context.HttpContext.User.Claims, context.DownstreamRequest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (response.IsError)
 | 
					                if (response.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("Error setting headers on context, setting pipeline error");
 | 
					                    Logger.LogWarning("Error setting headers on context, setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, response.Errors);
 | 
					                    SetPipelineError(context, response.Errors);
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _logger.LogDebug("headers have been set on context");
 | 
					                Logger.LogInformation("headers have been set on context");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await _next.Invoke(context);
 | 
					            await _next.Invoke(context);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,10 +26,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (splits.Length < index || index < 0)
 | 
					            if (splits.Length < index || index < 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse<string>(new List<Error>
 | 
					                return new ErrorResponse<string>(new CannotFindClaimError($"Cannot find claim for key: {key}, delimiter: {delimiter}, index: {index}"));
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    new CannotFindClaimError($"Cannot find claim for key: {key}, delimiter: {delimiter}, index: {index}")
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var value = splits[index];
 | 
					            var value = splits[index];
 | 
				
			||||||
@@ -55,10 +52,7 @@
 | 
				
			|||||||
                return new OkResponse<string>(claim.Value);
 | 
					                return new OkResponse<string>(claim.Value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new ErrorResponse<string>(new List<Error>
 | 
					            return new ErrorResponse<string>(new CannotFindClaimError($"Cannot find claim for key: {key}"));
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                new CannotFindClaimError($"Cannot find claim for key: {key}")
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ using System.Linq;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Infrastructure.Extensions
 | 
					namespace Ocelot.Infrastructure.Extensions
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    internal static class StringValueExtensions
 | 
					    internal static class StringValuesExtensions
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static string GetValue(this StringValues stringValues)
 | 
					        public static string GetValue(this StringValues stringValues)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -11,6 +11,7 @@ namespace Ocelot.Infrastructure.Extensions
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                return stringValues;
 | 
					                return stringValues;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return stringValues.ToArray().LastOrDefault();
 | 
					            return stringValues.ToArray().LastOrDefault();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,10 +24,7 @@ namespace Ocelot.Infrastructure.RequestData
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse(new List<Error>
 | 
					                return new ErrorResponse(new CannotAddDataError(string.Format($"Unable to add data for key: {key}, exception: {exception.Message}")));
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    new CannotAddDataError(string.Format($"Unable to add data for key: {key}, exception: {exception.Message}"))
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,10 +37,7 @@ namespace Ocelot.Infrastructure.RequestData
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse(new List<Error>
 | 
					                return new ErrorResponse(new CannotAddDataError(string.Format($"Unable to update data for key: {key}, exception: {exception.Message}")));
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    new CannotAddDataError(string.Format($"Unable to update data for key: {key}, exception: {exception.Message}"))
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,10 +47,7 @@ namespace Ocelot.Infrastructure.RequestData
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if(_httpContextAccessor.HttpContext == null || _httpContextAccessor.HttpContext.Items == null)
 | 
					            if(_httpContextAccessor.HttpContext == null || _httpContextAccessor.HttpContext.Items == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse<T>(new List<Error>
 | 
					                return new ErrorResponse<T>(new CannotFindDataError($"Unable to find data for key: {key} because HttpContext or HttpContext.Items is null"));
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    new CannotFindDataError($"Unable to find data for key: {key} because HttpContext or HttpContext.Items is null")
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(_httpContextAccessor.HttpContext.Items.TryGetValue(key, out obj))
 | 
					            if(_httpContextAccessor.HttpContext.Items.TryGetValue(key, out obj))
 | 
				
			||||||
@@ -65,10 +56,7 @@ namespace Ocelot.Infrastructure.RequestData
 | 
				
			|||||||
                return new OkResponse<T>(data);
 | 
					                return new OkResponse<T>(data);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new ErrorResponse<T>(new List<Error>
 | 
					            return new ErrorResponse<T>(new CannotFindDataError($"Unable to find data for key: {key}"));
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                new CannotFindDataError($"Unable to find data for key: {key}")
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,12 +28,12 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (services == null)
 | 
					            if (services == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse<ServiceHostAndPort>(new List<Error>() { new ServicesAreNullError($"services were null for {_serviceName}") });
 | 
					                return new ErrorResponse<ServiceHostAndPort>(new ServicesAreNullError($"services were null for {_serviceName}") );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!services.Any())
 | 
					            if (!services.Any())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new ErrorResponse<ServiceHostAndPort>(new List<Error>() { new ServicesAreEmptyError($"services were empty for {_serviceName}") });
 | 
					                return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError($"services were empty for {_serviceName}"));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lock(_syncLock)
 | 
					            lock(_syncLock)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,15 +9,14 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
				
			|||||||
    public class LoadBalancingMiddleware : OcelotMiddleware
 | 
					    public class LoadBalancingMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly ILoadBalancerHouse _loadBalancerHouse;
 | 
					        private readonly ILoadBalancerHouse _loadBalancerHouse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public LoadBalancingMiddleware(OcelotRequestDelegate next,
 | 
					        public LoadBalancingMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            ILoadBalancerHouse loadBalancerHouse) 
 | 
					            ILoadBalancerHouse loadBalancerHouse) 
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<LoadBalancingMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<LoadBalancingMiddleware>();
 | 
					 | 
				
			||||||
            _loadBalancerHouse = loadBalancerHouse;
 | 
					            _loadBalancerHouse = loadBalancerHouse;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,7 +25,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
				
			|||||||
            var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration);
 | 
					            var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration);
 | 
				
			||||||
            if(loadBalancer.IsError)
 | 
					            if(loadBalancer.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
 | 
					                Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
 | 
				
			||||||
                SetPipelineError(context, loadBalancer.Errors);
 | 
					                SetPipelineError(context, loadBalancer.Errors);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -34,7 +33,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
				
			|||||||
            var hostAndPort = await loadBalancer.Data.Lease();
 | 
					            var hostAndPort = await loadBalancer.Data.Lease();
 | 
				
			||||||
            if(hostAndPort.IsError)
 | 
					            if(hostAndPort.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
 | 
					                Logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
 | 
				
			||||||
                SetPipelineError(context, hostAndPort.Errors);
 | 
					                SetPipelineError(context, hostAndPort.Errors);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -52,7 +51,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception)
 | 
					            catch (Exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
 | 
					                Logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
 | 
				
			||||||
                throw;
 | 
					                throw;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using Microsoft.Extensions.Logging;
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
using Microsoft.Extensions.Logging.Internal;
 | 
					 | 
				
			||||||
using Ocelot.Infrastructure.RequestData;
 | 
					using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Logging
 | 
					namespace Ocelot.Logging
 | 
				
			||||||
@@ -10,34 +9,38 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        private readonly ILogger _logger;
 | 
					        private readonly ILogger _logger;
 | 
				
			||||||
        private readonly IRequestScopedDataRepository _scopedDataRepository;
 | 
					        private readonly IRequestScopedDataRepository _scopedDataRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Name { get; }
 | 
					        public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository, string typeName)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Name = typeName;
 | 
					 | 
				
			||||||
            _logger = logger;
 | 
					            _logger = logger;
 | 
				
			||||||
            _scopedDataRepository = scopedDataRepository;
 | 
					            _scopedDataRepository = scopedDataRepository;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void LogTrace(string message, params object[] args)
 | 
					        public void LogTrace(string message)
 | 
				
			||||||
        {            
 | 
					        {            
 | 
				
			||||||
            var requestId = GetOcelotRequestId();
 | 
					            var requestId = GetOcelotRequestId();
 | 
				
			||||||
            var previousRequestId = GetOcelotPreviousRequestId();
 | 
					            var previousRequestId = GetOcelotPreviousRequestId();
 | 
				
			||||||
            _logger.LogTrace("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, new FormattedLogValues(message, args).ToString());
 | 
					            _logger.LogTrace("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void LogDebug(string message, params object[] args)
 | 
					        public void LogDebug(string message)
 | 
				
			||||||
        {            
 | 
					        {            
 | 
				
			||||||
            var requestId = GetOcelotRequestId();
 | 
					            var requestId = GetOcelotRequestId();
 | 
				
			||||||
            var previousRequestId = GetOcelotPreviousRequestId();
 | 
					            var previousRequestId = GetOcelotPreviousRequestId();
 | 
				
			||||||
            _logger.LogDebug("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, new FormattedLogValues(message, args).ToString());
 | 
					            _logger.LogDebug("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void LogInformation(string message, params object[] args)
 | 
					        public void LogInformation(string message)
 | 
				
			||||||
        {            
 | 
					        {            
 | 
				
			||||||
            var requestId = GetOcelotRequestId();
 | 
					            var requestId = GetOcelotRequestId();
 | 
				
			||||||
            var previousRequestId = GetOcelotPreviousRequestId();
 | 
					            var previousRequestId = GetOcelotPreviousRequestId();
 | 
				
			||||||
            _logger.LogInformation("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, new FormattedLogValues(message, args).ToString());
 | 
					            _logger.LogInformation("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void LogWarning(string message)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var requestId = GetOcelotRequestId();
 | 
				
			||||||
 | 
					            var previousRequestId = GetOcelotPreviousRequestId();
 | 
				
			||||||
 | 
					            _logger.LogWarning("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void LogError(string message, Exception exception)
 | 
					        public void LogError(string message, Exception exception)
 | 
				
			||||||
@@ -47,18 +50,11 @@ namespace Ocelot.Logging
 | 
				
			|||||||
            _logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception);
 | 
					            _logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void LogError(string message, params object[] args)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var requestId = GetOcelotRequestId();
 | 
					 | 
				
			||||||
            var previousRequestId = GetOcelotPreviousRequestId();
 | 
					 | 
				
			||||||
            _logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, new FormattedLogValues(message, args).ToString());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public void LogCritical(string message, Exception exception)
 | 
					        public void LogCritical(string message, Exception exception)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var requestId = GetOcelotRequestId();
 | 
					            var requestId = GetOcelotRequestId();
 | 
				
			||||||
            var previousRequestId = GetOcelotPreviousRequestId();
 | 
					            var previousRequestId = GetOcelotPreviousRequestId();
 | 
				
			||||||
            _logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
 | 
					            _logger.LogCritical("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private string GetOcelotRequestId()
 | 
					        private string GetOcelotRequestId()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        public IOcelotLogger CreateLogger<T>()
 | 
					        public IOcelotLogger CreateLogger<T>()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var logger = _loggerFactory.CreateLogger<T>();
 | 
					            var logger = _loggerFactory.CreateLogger<T>();
 | 
				
			||||||
            return new AspDotNetLogger(logger, _scopedDataRepository, typeof(T).Name);
 | 
					            return new AspDotNetLogger(logger, _scopedDataRepository);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -7,16 +7,11 @@ namespace Ocelot.Logging
 | 
				
			|||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public interface IOcelotLogger
 | 
					    public interface IOcelotLogger
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        void LogTrace(string message, params object[] args);
 | 
					        void LogTrace(string message);
 | 
				
			||||||
        void LogDebug(string message, params object[] args);
 | 
					        void LogDebug(string message);
 | 
				
			||||||
        void LogInformation(string message, params object[] args);
 | 
					        void LogInformation(string message);
 | 
				
			||||||
 | 
					        void LogWarning(string message);
 | 
				
			||||||
        void LogError(string message, Exception exception);
 | 
					        void LogError(string message, Exception exception);
 | 
				
			||||||
        void LogError(string message, params object[] args);
 | 
					 | 
				
			||||||
        void LogCritical(string message, Exception exception);
 | 
					        void LogCritical(string message, Exception exception);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// The name of the type the logger has been built for.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        string Name { get; }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,15 +8,14 @@ using Butterfly.Client.Tracing;
 | 
				
			|||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using Ocelot.Infrastructure.Extensions;
 | 
					using Ocelot.Infrastructure.Extensions;
 | 
				
			||||||
using Microsoft.Extensions.Logging;
 | 
					 | 
				
			||||||
using Ocelot.Requester;
 | 
					using Ocelot.Requester;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Logging
 | 
					namespace Ocelot.Logging
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class OcelotDiagnosticListener
 | 
					    public class OcelotDiagnosticListener
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private IServiceTracer _tracer;
 | 
					        private readonly IServiceTracer _tracer;
 | 
				
			||||||
        private IOcelotLogger _logger;
 | 
					        private readonly IOcelotLogger _logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceTracer tracer)
 | 
					        public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceTracer tracer)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -27,7 +26,7 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        [DiagnosticName("Ocelot.MiddlewareException")]
 | 
					        [DiagnosticName("Ocelot.MiddlewareException")]
 | 
				
			||||||
        public virtual void OcelotMiddlewareException(Exception exception, DownstreamContext context, string name)
 | 
					        public virtual void OcelotMiddlewareException(Exception exception, DownstreamContext context, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogTrace($"Ocelot.MiddlewareException: {name}; {exception.Message}");
 | 
					            _logger.LogTrace($"Ocelot.MiddlewareException: {name}; {exception.Message};");
 | 
				
			||||||
            Event(context.HttpContext, $"Ocelot.MiddlewareStarted: {name}; {context.HttpContext.Request.Path}");
 | 
					            Event(context.HttpContext, $"Ocelot.MiddlewareStarted: {name}; {context.HttpContext.Request.Path}");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,7 +40,7 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        [DiagnosticName("Ocelot.MiddlewareFinished")]
 | 
					        [DiagnosticName("Ocelot.MiddlewareFinished")]
 | 
				
			||||||
        public virtual void OcelotMiddlewareFinished(DownstreamContext context, string name)
 | 
					        public virtual void OcelotMiddlewareFinished(DownstreamContext context, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogTrace($"OcelotMiddlewareFinished: {name}; {context.HttpContext.Request.Path}");
 | 
					            _logger.LogTrace($"Ocelot.MiddlewareFinished: {name}; {context.HttpContext.Request.Path}");
 | 
				
			||||||
            Event(context.HttpContext, $"OcelotMiddlewareFinished: {name}; {context.HttpContext.Request.Path}");
 | 
					            Event(context.HttpContext, $"OcelotMiddlewareFinished: {name}; {context.HttpContext.Request.Path}");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,7 +54,7 @@ namespace Ocelot.Logging
 | 
				
			|||||||
        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
 | 
					        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
 | 
				
			||||||
        public virtual void OnMiddlewareException(Exception exception, string name)
 | 
					        public virtual void OnMiddlewareException(Exception exception, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogTrace($"MiddlewareException: {name}; {exception.Message}");
 | 
					            _logger.LogTrace($"MiddlewareException: {name}; {exception.Message};");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")]
 | 
					        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")]
 | 
				
			||||||
@@ -67,16 +66,17 @@ namespace Ocelot.Logging
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void Event(HttpContext httpContext, string @event)
 | 
					        private void Event(HttpContext httpContext, string @event)
 | 
				
			||||||
        {  
 | 
					        {  
 | 
				
			||||||
            // Hack - if the user isnt using tracing the code gets here and will blow up on 
 | 
					            // todo - if the user isnt using tracing the code gets here and will blow up on 
 | 
				
			||||||
            // _tracer.Tracer.TryExtract. We already use the fake tracer for another scenario
 | 
					            // _tracer.Tracer.TryExtract. We already use the fake tracer for another scenario
 | 
				
			||||||
            // so sticking it here as well..I guess we need a factory for this but no idea
 | 
					            // so sticking it here as well..I guess we need a factory for this but cba to do it at
 | 
				
			||||||
            // how to hook that into the diagnostic framework at the moment.
 | 
					            // the moment
 | 
				
			||||||
            if(_tracer.GetType() == typeof(FakeServiceTracer))
 | 
					            if(_tracer.GetType() == typeof(FakeServiceTracer))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var span = httpContext.GetSpan();
 | 
					            var span = httpContext.GetSpan();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(span == null)
 | 
					            if(span == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var spanBuilder = new SpanBuilder($"server {httpContext.Request.Method} {httpContext.Request.Path}");
 | 
					                var spanBuilder = new SpanBuilder($"server {httpContext.Request.Method} {httpContext.Request.Path}");
 | 
				
			||||||
@@ -84,10 +84,12 @@ namespace Ocelot.Logging
 | 
				
			|||||||
                    c => c.Select(x => new KeyValuePair<string, string>(x.Key, x.Value.GetValue())).GetEnumerator()))
 | 
					                    c => c.Select(x => new KeyValuePair<string, string>(x.Key, x.Value.GetValue())).GetEnumerator()))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    spanBuilder.AsChildOf(spanContext);
 | 
					                    spanBuilder.AsChildOf(spanContext);
 | 
				
			||||||
                };
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                span = _tracer.Start(spanBuilder);        
 | 
					                span = _tracer.Start(spanBuilder);        
 | 
				
			||||||
                httpContext.SetSpan(span);   
 | 
					                httpContext.SetSpan(span);   
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            span?.Log(LogField.CreateNew().Event(@event));
 | 
					            span?.Log(LogField.CreateNew().Event(@event));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,17 +13,24 @@ namespace Ocelot.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        public DownstreamContext(HttpContext httpContext)
 | 
					        public DownstreamContext(HttpContext httpContext)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.HttpContext = httpContext;
 | 
					            HttpContext = httpContext;
 | 
				
			||||||
            Errors = new List<Error>();
 | 
					            Errors = new List<Error>();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
 | 
					        public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
 | 
					        public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
 | 
				
			||||||
        public HttpContext HttpContext { get; private set; }
 | 
					
 | 
				
			||||||
 | 
					        public HttpContext HttpContext { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DownstreamReRoute DownstreamReRoute { get; set; }
 | 
					        public DownstreamReRoute DownstreamReRoute { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DownstreamRequest DownstreamRequest { get; set; }
 | 
					        public DownstreamRequest DownstreamRequest { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public HttpResponseMessage DownstreamResponse { get; set; }
 | 
					        public HttpResponseMessage DownstreamResponse { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public List<Error> Errors { get;set; }
 | 
					        public List<Error> Errors { get;set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsError => Errors.Count > 0;
 | 
					        public bool IsError => Errors.Count > 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,33 @@
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using Ocelot.Errors;
 | 
					using Ocelot.Errors;
 | 
				
			||||||
 | 
					using Ocelot.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Middleware
 | 
					namespace Ocelot.Middleware
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public abstract class OcelotMiddleware
 | 
					    public abstract class OcelotMiddleware
 | 
				
			||||||
    {        
 | 
					    {        
 | 
				
			||||||
        protected OcelotMiddleware()
 | 
					        protected OcelotMiddleware(IOcelotLogger logger)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            Logger = logger;
 | 
				
			||||||
            MiddlewareName = this.GetType().Name;
 | 
					            MiddlewareName = this.GetType().Name;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IOcelotLogger Logger { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string MiddlewareName { get; }
 | 
					        public string MiddlewareName { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void SetPipelineError(DownstreamContext context, List<Error> errors)
 | 
					        public void SetPipelineError(DownstreamContext context, List<Error> errors)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            context.Errors = errors;
 | 
					            foreach(var error in errors)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                SetPipelineError(context, error);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void SetPipelineError(DownstreamContext context, Error error)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Logger.LogWarning(error.Message);
 | 
				
			||||||
 | 
					            context.Errors.Add(error);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,7 +88,7 @@ namespace Ocelot.Middleware.Pipeline
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        catch(Exception ex)
 | 
					                        catch(Exception ex)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            Write(diagnosticListener, "Ocelot.MiddlewareException", middlewareName, context);
 | 
					                            WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context);
 | 
				
			||||||
                            throw ex;
 | 
					                            throw ex;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        finally
 | 
					                        finally
 | 
				
			||||||
@@ -123,6 +123,14 @@ namespace Ocelot.Middleware.Pipeline
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static void WriteException(DiagnosticListener diagnosticListener, Exception exception, string message, string middlewareName, DownstreamContext context)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(diagnosticListener != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                diagnosticListener.Write(message, new { name = middlewareName, context = context, exception = exception });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static IOcelotPipelineBuilder MapWhen(this IOcelotPipelineBuilder app, Predicate predicate, Action<IOcelotPipelineBuilder> configuration)
 | 
					        public static IOcelotPipelineBuilder MapWhen(this IOcelotPipelineBuilder app, Predicate predicate, Action<IOcelotPipelineBuilder> configuration)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (app == null)
 | 
					            if (app == null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,28 +12,27 @@ namespace Ocelot.QueryStrings.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IAddQueriesToRequest _addQueriesToRequest;
 | 
					        private readonly IAddQueriesToRequest _addQueriesToRequest;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public QueryStringBuilderMiddleware(OcelotRequestDelegate next,
 | 
					        public QueryStringBuilderMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IAddQueriesToRequest addQueriesToRequest) 
 | 
					            IAddQueriesToRequest addQueriesToRequest) 
 | 
				
			||||||
 | 
					                : base(loggerFactory.CreateLogger<QueryStringBuilderMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _addQueriesToRequest = addQueriesToRequest;
 | 
					            _addQueriesToRequest = addQueriesToRequest;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<QueryStringBuilderMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (context.DownstreamReRoute.ClaimsToQueries.Any())
 | 
					            if (context.DownstreamReRoute.ClaimsToQueries.Any())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
 | 
					                Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(context.DownstreamReRoute.ClaimsToQueries, context.HttpContext.User.Claims, context.DownstreamRequest);
 | 
					                var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(context.DownstreamReRoute.ClaimsToQueries, context.HttpContext.User.Claims, context.DownstreamRequest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (response.IsError)
 | 
					                if (response.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogDebug("there was an error setting queries on context, setting pipeline error");
 | 
					                    Logger.LogWarning("there was an error setting queries on context, setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SetPipelineError(context, response.Errors);
 | 
					                    SetPipelineError(context, response.Errors);
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,9 +40,13 @@ namespace Ocelot.Raft
 | 
				
			|||||||
            using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
					            using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var json = await reader.ReadToEndAsync();
 | 
					                var json = await reader.ReadToEndAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var appendEntries = JsonConvert.DeserializeObject<AppendEntries>(json, _jsonSerialiserSettings);
 | 
					                var appendEntries = JsonConvert.DeserializeObject<AppendEntries>(json, _jsonSerialiserSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _logger.LogDebug($"{_baseSchemeUrlAndPort}/appendentries called, my state is {_node.State.GetType().FullName}");
 | 
					                _logger.LogDebug($"{_baseSchemeUrlAndPort}/appendentries called, my state is {_node.State.GetType().FullName}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var appendEntriesResponse = _node.Handle(appendEntries);
 | 
					                var appendEntriesResponse = _node.Handle(appendEntries);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return new OkObjectResult(appendEntriesResponse);
 | 
					                return new OkObjectResult(appendEntriesResponse);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -53,9 +57,13 @@ namespace Ocelot.Raft
 | 
				
			|||||||
            using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
					            using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var json = await reader.ReadToEndAsync();
 | 
					                var json = await reader.ReadToEndAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var requestVote = JsonConvert.DeserializeObject<RequestVote>(json, _jsonSerialiserSettings);
 | 
					                var requestVote = JsonConvert.DeserializeObject<RequestVote>(json, _jsonSerialiserSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _logger.LogDebug($"{_baseSchemeUrlAndPort}/requestvote called, my state is {_node.State.GetType().FullName}");
 | 
					                _logger.LogDebug($"{_baseSchemeUrlAndPort}/requestvote called, my state is {_node.State.GetType().FullName}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var requestVoteResponse = _node.Handle(requestVote);
 | 
					                var requestVoteResponse = _node.Handle(requestVote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return new OkObjectResult(requestVoteResponse);
 | 
					                return new OkObjectResult(requestVoteResponse);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -68,10 +76,15 @@ namespace Ocelot.Raft
 | 
				
			|||||||
                using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
					                using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var json = await reader.ReadToEndAsync();
 | 
					                    var json = await reader.ReadToEndAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    var command = JsonConvert.DeserializeObject<ICommand>(json, _jsonSerialiserSettings);
 | 
					                    var command = JsonConvert.DeserializeObject<ICommand>(json, _jsonSerialiserSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    _logger.LogDebug($"{_baseSchemeUrlAndPort}/command called, my state is {_node.State.GetType().FullName}");
 | 
					                    _logger.LogDebug($"{_baseSchemeUrlAndPort}/command called, my state is {_node.State.GetType().FullName}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    var commandResponse = _node.Accept(command);
 | 
					                    var commandResponse = _node.Accept(command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    json = JsonConvert.SerializeObject(commandResponse, _jsonSerialiserSettings);
 | 
					                    json = JsonConvert.SerializeObject(commandResponse, _jsonSerialiserSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return StatusCode(200, json);
 | 
					                    return StatusCode(200, json);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,16 +14,15 @@ namespace Ocelot.RateLimit.Middleware
 | 
				
			|||||||
    public class ClientRateLimitMiddleware : OcelotMiddleware
 | 
					    public class ClientRateLimitMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly IRateLimitCounterHandler _counterHandler;
 | 
					        private readonly IRateLimitCounterHandler _counterHandler;
 | 
				
			||||||
        private readonly ClientRateLimitProcessor _processor;
 | 
					        private readonly ClientRateLimitProcessor _processor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ClientRateLimitMiddleware(OcelotRequestDelegate next,
 | 
					        public ClientRateLimitMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IRateLimitCounterHandler counterHandler)
 | 
					            IRateLimitCounterHandler counterHandler)
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<ClientRateLimitMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<ClientRateLimitMiddleware>();
 | 
					 | 
				
			||||||
            _counterHandler = counterHandler;
 | 
					            _counterHandler = counterHandler;
 | 
				
			||||||
            _processor = new ClientRateLimitProcessor(counterHandler);
 | 
					            _processor = new ClientRateLimitProcessor(counterHandler);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -35,7 +34,7 @@ namespace Ocelot.RateLimit.Middleware
 | 
				
			|||||||
            // check if rate limiting is enabled
 | 
					            // check if rate limiting is enabled
 | 
				
			||||||
            if (!context.DownstreamReRoute.EnableEndpointEndpointRateLimiting)
 | 
					            if (!context.DownstreamReRoute.EnableEndpointEndpointRateLimiting)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"EndpointRateLimiting is not enabled for {context.DownstreamReRoute.DownstreamPathTemplate}");
 | 
					                Logger.LogInformation($"EndpointRateLimiting is not enabled for {context.DownstreamReRoute.DownstreamPathTemplate.Value}");
 | 
				
			||||||
                await _next.Invoke(context);
 | 
					                await _next.Invoke(context);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -46,7 +45,7 @@ namespace Ocelot.RateLimit.Middleware
 | 
				
			|||||||
            // check white list
 | 
					            // check white list
 | 
				
			||||||
            if (IsWhitelisted(identity, options))
 | 
					            if (IsWhitelisted(identity, options))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug($"{context.DownstreamReRoute.DownstreamPathTemplate} is white listed from rate limiting");
 | 
					                Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} is white listed from rate limiting");
 | 
				
			||||||
                await _next.Invoke(context);
 | 
					                await _next.Invoke(context);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -112,7 +111,8 @@ namespace Ocelot.RateLimit.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule, DownstreamReRoute downstreamReRoute)
 | 
					        public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule, DownstreamReRoute downstreamReRoute)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogDebug($"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule { downstreamReRoute.UpstreamPathTemplate }, TraceIdentifier {httpContext.TraceIdentifier}.");
 | 
					            Logger.LogInformation(
 | 
				
			||||||
 | 
					                $"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule { downstreamReRoute.UpstreamPathTemplate.Value }, TraceIdentifier {httpContext.TraceIdentifier}.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public virtual Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitOptions option, string retryAfter)
 | 
					        public virtual Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitOptions option, string retryAfter)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,5 +65,10 @@ namespace Ocelot.Request.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            return uriBuilder.Uri.AbsoluteUri;
 | 
					            return uriBuilder.Uri.AbsoluteUri;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override string ToString() 
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ToUri();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,15 +11,14 @@ namespace Ocelot.Request.Middleware
 | 
				
			|||||||
    public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
 | 
					    public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly Mapper.IRequestMapper _requestMapper;
 | 
					        private readonly Mapper.IRequestMapper _requestMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DownstreamRequestInitialiserMiddleware(OcelotRequestDelegate next,
 | 
					        public DownstreamRequestInitialiserMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            Mapper.IRequestMapper requestMapper)
 | 
					            Mapper.IRequestMapper requestMapper)
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>();
 | 
					 | 
				
			||||||
            _requestMapper = requestMapper;
 | 
					            _requestMapper = requestMapper;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,11 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					 | 
				
			||||||
using Microsoft.Extensions.Primitives;
 | 
					 | 
				
			||||||
using Ocelot.Infrastructure.RequestData;
 | 
					using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
using Ocelot.Logging;
 | 
					using Ocelot.Logging;
 | 
				
			||||||
using Ocelot.Middleware;
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
using System.Net.Http;
 | 
					 | 
				
			||||||
using System.Net.Http.Headers;
 | 
					using System.Net.Http.Headers;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using Ocelot.DownstreamRouteFinder.Middleware;
 | 
					 | 
				
			||||||
using Ocelot.Request.Middleware;
 | 
					using Ocelot.Request.Middleware;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.RequestId.Middleware
 | 
					namespace Ocelot.RequestId.Middleware
 | 
				
			||||||
@@ -16,16 +13,15 @@ namespace Ocelot.RequestId.Middleware
 | 
				
			|||||||
    public class ReRouteRequestIdMiddleware : OcelotMiddleware
 | 
					    public class ReRouteRequestIdMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
        private readonly IRequestScopedDataRepository _requestScopedDataRepository;
 | 
					        private readonly IRequestScopedDataRepository _requestScopedDataRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ReRouteRequestIdMiddleware(OcelotRequestDelegate next,
 | 
					        public ReRouteRequestIdMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory, 
 | 
					            IOcelotLoggerFactory loggerFactory, 
 | 
				
			||||||
            IRequestScopedDataRepository requestScopedDataRepository)
 | 
					            IRequestScopedDataRepository requestScopedDataRepository)
 | 
				
			||||||
 | 
					                : base(loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _requestScopedDataRepository = requestScopedDataRepository;
 | 
					            _requestScopedDataRepository = requestScopedDataRepository;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
@@ -39,25 +35,22 @@ namespace Ocelot.RequestId.Middleware
 | 
				
			|||||||
            // if get request ID is set on upstream request then retrieve it
 | 
					            // if get request ID is set on upstream request then retrieve it
 | 
				
			||||||
            var key = context.DownstreamReRoute.RequestIdKey ?? DefaultRequestIdKey.Value;
 | 
					            var key = context.DownstreamReRoute.RequestIdKey ?? DefaultRequestIdKey.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            StringValues upstreamRequestIds;
 | 
					            if (context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
 | 
				
			||||||
            if (context.HttpContext.Request.Headers.TryGetValue(key, out upstreamRequestIds))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                //set the traceidentifier
 | 
					 | 
				
			||||||
                context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
 | 
					                context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                //todo fix looking in both places
 | 
					 | 
				
			||||||
                //check if we have previous id in scoped repo
 | 
					                //check if we have previous id in scoped repo
 | 
				
			||||||
                var previousRequestId = _requestScopedDataRepository.Get<string>("RequestId");
 | 
					                var previousRequestId = _requestScopedDataRepository.Get<string>("RequestId");
 | 
				
			||||||
                if (!previousRequestId.IsError && !string.IsNullOrEmpty(previousRequestId.Data))
 | 
					                if (!previousRequestId.IsError && !string.IsNullOrEmpty(previousRequestId.Data) && previousRequestId.Data != context.HttpContext.TraceIdentifier)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    //we have a previous request id lets store it and update request id
 | 
					                    //we have a previous request id lets store it and update request id
 | 
				
			||||||
                    _requestScopedDataRepository.Add<string>("PreviousRequestId", previousRequestId.Data);
 | 
					                    _requestScopedDataRepository.Add("PreviousRequestId", previousRequestId.Data);
 | 
				
			||||||
                    _requestScopedDataRepository.Update<string>("RequestId", context.HttpContext.TraceIdentifier);
 | 
					                    _requestScopedDataRepository.Update("RequestId", context.HttpContext.TraceIdentifier);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    //else just add request id
 | 
					                    //else just add request id
 | 
				
			||||||
                    _requestScopedDataRepository.Add<string>("RequestId", context.HttpContext.TraceIdentifier);
 | 
					                    _requestScopedDataRepository.Add("RequestId", context.HttpContext.TraceIdentifier);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,15 +12,14 @@ namespace Ocelot.Requester.Middleware
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IHttpRequester _requester;
 | 
					        private readonly IHttpRequester _requester;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public HttpRequesterMiddleware(OcelotRequestDelegate next,
 | 
					        public HttpRequesterMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IHttpRequester requester)
 | 
					            IHttpRequester requester)
 | 
				
			||||||
 | 
					                : base(loggerFactory.CreateLogger<HttpRequesterMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _requester = requester;
 | 
					            _requester = requester;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<HttpRequesterMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
@@ -29,13 +28,13 @@ namespace Ocelot.Requester.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (response.IsError)
 | 
					            if (response.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("IHttpRequester returned an error, setting pipeline error");
 | 
					                Logger.LogDebug("IHttpRequester returned an error, setting pipeline error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SetPipelineError(context, response.Errors);
 | 
					                SetPipelineError(context, response.Errors);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug("setting http response message");
 | 
					            Logger.LogDebug("setting http response message");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            context.DownstreamResponse = response.Data;
 | 
					            context.DownstreamResponse = response.Data;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Net.Http;
 | 
					using System.Net.Http;
 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
@@ -13,7 +12,7 @@ namespace Ocelot.Requester
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly IServiceTracer _tracer;
 | 
					        private readonly IServiceTracer _tracer;
 | 
				
			||||||
        private readonly IRequestScopedDataRepository _repo;
 | 
					        private readonly IRequestScopedDataRepository _repo;
 | 
				
			||||||
        private const string prefix_spanId = "ot-spanId";
 | 
					        private const string PrefixSpanId = "ot-spanId";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public OcelotHttpTracingHandler(
 | 
					        public OcelotHttpTracingHandler(
 | 
				
			||||||
            IServiceTracer tracer, 
 | 
					            IServiceTracer tracer, 
 | 
				
			||||||
@@ -37,11 +36,10 @@ namespace Ocelot.Requester
 | 
				
			|||||||
            HttpRequestMessage request, 
 | 
					            HttpRequestMessage request, 
 | 
				
			||||||
            CancellationToken cancellationToken)
 | 
					            CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            IEnumerable<string> traceIdVals = null;
 | 
					            if (request.Headers.Contains(PrefixSpanId))
 | 
				
			||||||
            if (request.Headers.TryGetValues(prefix_spanId, out traceIdVals))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                request.Headers.Remove(prefix_spanId);
 | 
					                request.Headers.Remove(PrefixSpanId);
 | 
				
			||||||
                request.Headers.TryAddWithoutValidation(prefix_spanId, span.SpanContext.SpanId);
 | 
					                request.Headers.TryAddWithoutValidation(PrefixSpanId, span.SpanContext.SpanId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _repo.Add("TraceId", span.SpanContext.TraceId);
 | 
					            _repo.Add("TraceId", span.SpanContext.TraceId);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ using Ocelot.Middleware;
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Ocelot.DownstreamRouteFinder.Middleware;
 | 
					using Ocelot.DownstreamRouteFinder.Middleware;
 | 
				
			||||||
 | 
					using Ocelot.Infrastructure.Extensions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ocelot.Responder.Middleware
 | 
					namespace Ocelot.Responder.Middleware
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -17,18 +18,17 @@ namespace Ocelot.Responder.Middleware
 | 
				
			|||||||
        private readonly OcelotRequestDelegate _next;
 | 
					        private readonly OcelotRequestDelegate _next;
 | 
				
			||||||
        private readonly IHttpResponder _responder;
 | 
					        private readonly IHttpResponder _responder;
 | 
				
			||||||
        private readonly IErrorsToHttpStatusCodeMapper _codeMapper;
 | 
					        private readonly IErrorsToHttpStatusCodeMapper _codeMapper;
 | 
				
			||||||
        private readonly IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ResponderMiddleware(OcelotRequestDelegate next, 
 | 
					        public ResponderMiddleware(OcelotRequestDelegate next, 
 | 
				
			||||||
            IHttpResponder responder,
 | 
					            IHttpResponder responder,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory,
 | 
					            IOcelotLoggerFactory loggerFactory,
 | 
				
			||||||
            IErrorsToHttpStatusCodeMapper codeMapper
 | 
					            IErrorsToHttpStatusCodeMapper codeMapper
 | 
				
			||||||
           )
 | 
					           )
 | 
				
			||||||
 | 
					            :base(loggerFactory.CreateLogger<ResponderMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _responder = responder;
 | 
					            _responder = responder;
 | 
				
			||||||
            _codeMapper = codeMapper;
 | 
					            _codeMapper = codeMapper;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<ResponderMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
@@ -37,19 +37,13 @@ namespace Ocelot.Responder.Middleware
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (context.IsError)
 | 
					            if (context.IsError)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var errors = context.Errors;
 | 
					                Logger.LogWarning($"{context.Errors.ToErrorString()} errors found in {MiddlewareName}. Setting error response for request path:{context.HttpContext.Request.Path}, request method: {context.HttpContext.Request.Method}");
 | 
				
			||||||
                _logger.LogError($"{errors.Count} pipeline errors found in {MiddlewareName}. Setting error response status code");
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                foreach(var error in errors)
 | 
					                SetErrorResponse(context.HttpContext, context.Errors);
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    _logger.LogError(error.Message);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                SetErrorResponse(context.HttpContext, errors);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogDebug("no pipeline errors, setting and returning completed response");
 | 
					                Logger.LogDebug("no pipeline errors, setting and returning completed response");
 | 
				
			||||||
                await _responder.SetResponseOnHttpContext(context.HttpContext, context.DownstreamResponse);
 | 
					                await _responder.SetResponseOnHttpContext(context.HttpContext, context.DownstreamResponse);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,13 @@ namespace Ocelot.Responses
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class ErrorResponse : Response
 | 
					    public class ErrorResponse : Response
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public ErrorResponse(Error error) : base(new List<Error>{error})
 | 
					        public ErrorResponse(Error error) 
 | 
				
			||||||
 | 
					            : base(new List<Error>{error})
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ErrorResponse(List<Error> errors) : base(errors)
 | 
					        public ErrorResponse(List<Error> errors) 
 | 
				
			||||||
 | 
					            : base(errors)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,14 +15,8 @@ namespace Ocelot.Responses
 | 
				
			|||||||
            Errors = errors ?? new List<Error>();
 | 
					            Errors = errors ?? new List<Error>();
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public List<Error> Errors { get; private set; }
 | 
					        public List<Error> Errors { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsError
 | 
					        public bool IsError => Errors.Count > 0;
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return Errors.Count > 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -47,7 +47,7 @@ namespace Ocelot.ServiceDiscovery.Providers
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _logger.LogError($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
 | 
					                    _logger.LogWarning($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,13 +11,12 @@ namespace Ocelot.WebSockets.Middleware
 | 
				
			|||||||
    public class WebSocketsProxyMiddleware : OcelotMiddleware
 | 
					    public class WebSocketsProxyMiddleware : OcelotMiddleware
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private OcelotRequestDelegate _next;
 | 
					        private OcelotRequestDelegate _next;
 | 
				
			||||||
        private IOcelotLogger _logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public WebSocketsProxyMiddleware(OcelotRequestDelegate next,
 | 
					        public WebSocketsProxyMiddleware(OcelotRequestDelegate next,
 | 
				
			||||||
            IOcelotLoggerFactory loggerFactory)
 | 
					            IOcelotLoggerFactory loggerFactory)
 | 
				
			||||||
 | 
					                :base(loggerFactory.CreateLogger<WebSocketsProxyMiddleware>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _next = next;
 | 
					            _next = next;
 | 
				
			||||||
            _logger = loggerFactory.CreateLogger<WebSocketsProxyMiddleware>();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task Invoke(DownstreamContext context)
 | 
					        public async Task Invoke(DownstreamContext context)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,11 +37,11 @@ namespace Ocelot.ManualTest
 | 
				
			|||||||
                         {
 | 
					                         {
 | 
				
			||||||
                             x.WithDictionaryHandle();
 | 
					                             x.WithDictionaryHandle();
 | 
				
			||||||
                         })
 | 
					                         })
 | 
				
			||||||
                         .AddOpenTracing(option =>
 | 
					                       /*  .AddOpenTracing(option =>
 | 
				
			||||||
                         {
 | 
					                         {
 | 
				
			||||||
                             option.CollectorUrl = "http://localhost:9618";
 | 
					                             option.CollectorUrl = "http://localhost:9618";
 | 
				
			||||||
                             option.Service = "Ocelot.ManualTest";
 | 
					                             option.Service = "Ocelot.ManualTest";
 | 
				
			||||||
                         })
 | 
					                         })*/
 | 
				
			||||||
                         .AddAdministration("/administration", "secret");
 | 
					                         .AddAdministration("/administration", "secret");
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .ConfigureLogging((hostingContext, logging) =>
 | 
					                .ConfigureLogging((hostingContext, logging) =>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
  "Logging": {
 | 
					  "Logging": {
 | 
				
			||||||
    "IncludeScopes": false,
 | 
					    "IncludeScopes": false,
 | 
				
			||||||
    "LogLevel": {
 | 
					    "LogLevel": {
 | 
				
			||||||
      "Default": "Error",
 | 
					      "Default": "Trace",
 | 
				
			||||||
      "System": "Error",
 | 
					      "System": "Error",
 | 
				
			||||||
      "Microsoft": "Error"
 | 
					      "Microsoft": "Error"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
        private void ThenTheLoggerIsCalledCorrectly()
 | 
					        private void ThenTheLoggerIsCalledCorrectly()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger
 | 
					            _logger
 | 
				
			||||||
                .Verify(x => x.LogDebug(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
 | 
					                .Verify(x => x.LogDebug(It.IsAny<string>()), Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenClaimsToThingsAreReturned()
 | 
					        private void ThenClaimsToThingsAreReturned()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -124,7 +124,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void ThenTheLoggerIsCalledCorrectly(string message)
 | 
					        private void ThenTheLoggerIsCalledCorrectly(string message)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.Verify(x => x.LogError(message), Times.Once);
 | 
					            _logger.Verify(x => x.LogWarning(message), Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,3 @@
 | 
				
			|||||||
using Ocelot.Middleware;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Ocelot.UnitTests.Errors
 | 
					namespace Ocelot.UnitTests.Errors
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    using System;
 | 
					    using System;
 | 
				
			||||||
@@ -15,18 +13,18 @@ namespace Ocelot.UnitTests.Errors
 | 
				
			|||||||
    using Moq;
 | 
					    using Moq;
 | 
				
			||||||
    using Ocelot.Configuration;
 | 
					    using Ocelot.Configuration;
 | 
				
			||||||
    using Ocelot.Errors;
 | 
					    using Ocelot.Errors;
 | 
				
			||||||
    using Ocelot.DownstreamRouteFinder.Middleware;
 | 
					 | 
				
			||||||
    using Ocelot.Infrastructure.RequestData;
 | 
					    using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
 | 
					    using Ocelot.Middleware;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class ExceptionHandlerMiddlewareTests
 | 
					    public class ExceptionHandlerMiddlewareTests
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        bool _shouldThrowAnException = false;
 | 
					        bool _shouldThrowAnException;
 | 
				
			||||||
        private Mock<IOcelotConfigurationProvider> _provider;
 | 
					        private readonly Mock<IOcelotConfigurationProvider> _provider;
 | 
				
			||||||
        private Mock<IRequestScopedDataRepository> _repo;
 | 
					        private readonly Mock<IRequestScopedDataRepository> _repo;
 | 
				
			||||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
					        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
				
			||||||
        private Mock<IOcelotLogger> _logger;
 | 
					        private Mock<IOcelotLogger> _logger;
 | 
				
			||||||
        private ExceptionHandlerMiddleware _middleware;
 | 
					        private readonly ExceptionHandlerMiddleware _middleware;
 | 
				
			||||||
        private DownstreamContext _downstreamContext;
 | 
					        private readonly DownstreamContext _downstreamContext;
 | 
				
			||||||
        private OcelotRequestDelegate _next;
 | 
					        private OcelotRequestDelegate _next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ExceptionHandlerMiddlewareTests()
 | 
					        public ExceptionHandlerMiddlewareTests()
 | 
				
			||||||
@@ -59,7 +57,7 @@ namespace Ocelot.UnitTests.Errors
 | 
				
			|||||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
					                .And(_ => GivenTheConfigurationIs(config))
 | 
				
			||||||
                .When(_ => WhenICallTheMiddleware())
 | 
					                .When(_ => WhenICallTheMiddleware())
 | 
				
			||||||
                .Then(_ => ThenTheResponseIsOk())
 | 
					                .Then(_ => ThenTheResponseIsOk())
 | 
				
			||||||
                .And(_ => TheRequestIdIsNotSet())
 | 
					                .And(_ => TheAspDotnetRequestIdIsSet())
 | 
				
			||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,7 +87,7 @@ namespace Ocelot.UnitTests.Errors
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void ShouldNotSetRequestId()
 | 
					        public void ShouldSetAspDotNetRequestId()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
					            var config = new OcelotConfiguration(null, null, null, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -97,7 +95,7 @@ namespace Ocelot.UnitTests.Errors
 | 
				
			|||||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
					                .And(_ => GivenTheConfigurationIs(config))
 | 
				
			||||||
                .When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
 | 
					                .When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
 | 
				
			||||||
                .Then(_ => ThenTheResponseIsOk())
 | 
					                .Then(_ => ThenTheResponseIsOk())
 | 
				
			||||||
                .And(_ => TheRequestIdIsNotSet())
 | 
					                .And(_ => TheAspDotnetRequestIdIsSet())
 | 
				
			||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,29 +144,19 @@ namespace Ocelot.UnitTests.Errors
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void GivenTheConfigReturnsError()
 | 
					        private void GivenTheConfigReturnsError()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
					            var response = new Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
 | 
				
			||||||
 | 
					 | 
				
			||||||
            var response = new Ocelot.Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
 | 
					 | 
				
			||||||
            _provider
 | 
					            _provider
 | 
				
			||||||
                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
					                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public class FakeError : Error
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            public FakeError() 
 | 
					 | 
				
			||||||
                : base("meh", OcelotErrorCode.CannotAddDataError)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void TheRequestIdIsSet(string key, string value)
 | 
					        private void TheRequestIdIsSet(string key, string value)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _repo.Verify(x => x.Add<string>(key, value), Times.Once);
 | 
					            _repo.Verify(x => x.Add(key, value), Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenTheConfigurationIs(IOcelotConfiguration config)
 | 
					        private void GivenTheConfigurationIs(IOcelotConfiguration config)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var response = new Ocelot.Responses.OkResponse<IOcelotConfiguration>(config);
 | 
					            var response = new Responses.OkResponse<IOcelotConfiguration>(config);
 | 
				
			||||||
            _provider
 | 
					            _provider
 | 
				
			||||||
                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
					                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -193,9 +181,17 @@ namespace Ocelot.UnitTests.Errors
 | 
				
			|||||||
            _downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
 | 
					            _downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void TheRequestIdIsNotSet()
 | 
					        private void TheAspDotnetRequestIdIsSet()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _repo.Verify(x => x.Add<string>(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
 | 
					            _repo.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class FakeError : Error
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            internal FakeError()
 | 
				
			||||||
 | 
					                : base("meh", OcelotErrorCode.CannotAddDataError)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,7 +106,7 @@ namespace Ocelot.UnitTests.Headers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void ThenTheErrorIsLogged()
 | 
					        private void ThenTheErrorIsLogged()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.Verify(x => x.LogError("Unable to add header to response Trace-Id: {TraceId}"), Times.Once);
 | 
					            _logger.Verify(x => x.LogWarning("Unable to add header to response Trace-Id: {TraceId}"), Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenTheHeaderIsNotAdded(string key)
 | 
					        private void ThenTheHeaderIsNotAdded(string key)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										81
									
								
								test/Ocelot.UnitTests/Logging/AspDotNetLoggerTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								test/Ocelot.UnitTests/Logging/AspDotNetLoggerTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					namespace Ocelot.UnitTests.Logging
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using Moq;
 | 
				
			||||||
 | 
					    using Xunit;
 | 
				
			||||||
 | 
					    using Ocelot.Logging;
 | 
				
			||||||
 | 
					    using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					    using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
 | 
					    using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class AspDotNetLoggerTests
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly Mock<ILogger<object>> _coreLogger;
 | 
				
			||||||
 | 
					        private readonly AspDotNetLogger _logger; 
 | 
				
			||||||
 | 
					        private Mock<IRequestScopedDataRepository> _repo;
 | 
				
			||||||
 | 
					        private readonly string _b;
 | 
				
			||||||
 | 
					        private readonly string _a;
 | 
				
			||||||
 | 
					        private readonly Exception _ex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public AspDotNetLoggerTests()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _a = "tom";
 | 
				
			||||||
 | 
					            _b = "laura";
 | 
				
			||||||
 | 
					            _ex = new Exception("oh no");
 | 
				
			||||||
 | 
					            _coreLogger = new Mock<ILogger<object>>();
 | 
				
			||||||
 | 
					            _repo = new Mock<IRequestScopedDataRepository>();
 | 
				
			||||||
 | 
					            _logger = new AspDotNetLogger(_coreLogger.Object, _repo.Object);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_trace()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.LogTrace($"a message from {_a} to {_b}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ThenLevelIsLogged("requestId: no request id, previousRequestId: no previous request id, message: a message from tom to laura", LogLevel.Trace);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_info()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.LogInformation($"a message from {_a} to {_b}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ThenLevelIsLogged("requestId: no request id, previousRequestId: no previous request id, message: a message from tom to laura", LogLevel.Information);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_warning()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.LogWarning($"a message from {_a} to {_b}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ThenLevelIsLogged("requestId: no request id, previousRequestId: no previous request id, message: a message from tom to laura", LogLevel.Warning);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_error()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            _logger.LogError($"a message from {_a} to {_b}", _ex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ThenLevelIsLogged("requestId: no request id, previousRequestId: no previous request id, message: a message from tom to laura, exception: System.Exception: oh no", LogLevel.Error);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_critical()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.LogCritical($"a message from {_a} to {_b}", _ex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ThenLevelIsLogged("requestId: no request id, previousRequestId: no previous request id, message: a message from tom to laura, exception: System.Exception: oh no", LogLevel.Critical);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenLevelIsLogged(string expected, LogLevel expectedLogLevel)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _coreLogger.Verify(
 | 
				
			||||||
 | 
					                x => x.Log(
 | 
				
			||||||
 | 
					                    expectedLogLevel,
 | 
				
			||||||
 | 
					                    It.IsAny<EventId>(),
 | 
				
			||||||
 | 
					                    It.Is<object>(o => o.ToString() == expected), 
 | 
				
			||||||
 | 
					                    It.IsAny<Exception>(),
 | 
				
			||||||
 | 
					                    It.IsAny<Func<object, Exception, string>>()), Times.Once);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										145
									
								
								test/Ocelot.UnitTests/Logging/OcelotDiagnosticListenerTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								test/Ocelot.UnitTests/Logging/OcelotDiagnosticListenerTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					using Ocelot.Logging;
 | 
				
			||||||
 | 
					using Moq;
 | 
				
			||||||
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
 | 
					using Butterfly.Client.Tracing;
 | 
				
			||||||
 | 
					using Ocelot.Requester;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.UnitTests.Logging
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OcelotDiagnosticListenerTests
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly OcelotDiagnosticListener _listener;
 | 
				
			||||||
 | 
					        private Mock<IOcelotLoggerFactory> _factory;
 | 
				
			||||||
 | 
					        private readonly Mock<IOcelotLogger> _logger;
 | 
				
			||||||
 | 
					        private IServiceTracer _tracer;
 | 
				
			||||||
 | 
					        private DownstreamContext _downstreamContext;
 | 
				
			||||||
 | 
					        private string _name;
 | 
				
			||||||
 | 
					        private Exception _exception;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public OcelotDiagnosticListenerTests()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _factory = new Mock<IOcelotLoggerFactory>();
 | 
				
			||||||
 | 
					            _logger = new Mock<IOcelotLogger>();
 | 
				
			||||||
 | 
					            _tracer = new FakeServiceTracer();
 | 
				
			||||||
 | 
					            _factory.Setup(x => x.CreateLogger<OcelotDiagnosticListener>()).Returns(_logger.Object);
 | 
				
			||||||
 | 
					            _listener = new OcelotDiagnosticListener(_factory.Object, _tracer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_trace_ocelot_middleware_started()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(_ => GivenAMiddlewareName())
 | 
				
			||||||
 | 
					                .And(_ => GivenAContext())
 | 
				
			||||||
 | 
					                .When(_ => WhenOcelotMiddlewareStartedCalled())
 | 
				
			||||||
 | 
					                .Then(_ => ThenTheLogIs($"Ocelot.MiddlewareStarted: {_name}; {_downstreamContext.HttpContext.Request.Path}"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_trace_ocelot_middleware_finished()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(_ => GivenAMiddlewareName())
 | 
				
			||||||
 | 
					                .And(_ => GivenAContext())
 | 
				
			||||||
 | 
					                .When(_ => WhenOcelotMiddlewareFinishedCalled())
 | 
				
			||||||
 | 
					                .Then(_ => ThenTheLogIs($"Ocelot.MiddlewareFinished: {_name}; {_downstreamContext.HttpContext.Request.Path}"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_trace_ocelot_middleware_exception()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(_ => GivenAMiddlewareName())
 | 
				
			||||||
 | 
					                .And(_ => GivenAContext())
 | 
				
			||||||
 | 
					                .And(_ => GivenAException(new Exception("oh no")))
 | 
				
			||||||
 | 
					                .When(_ => WhenOcelotMiddlewareExceptionCalled())
 | 
				
			||||||
 | 
					                .Then(_ => ThenTheLogIs($"Ocelot.MiddlewareException: {_name}; {_exception.Message};"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       [Fact]
 | 
				
			||||||
 | 
					        public void should_trace_middleware_started()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(_ => GivenAMiddlewareName())
 | 
				
			||||||
 | 
					                .And(_ => GivenAContext())
 | 
				
			||||||
 | 
					                .When(_ => WhenMiddlewareStartedCalled())
 | 
				
			||||||
 | 
					                .Then(_ => ThenTheLogIs($"MiddlewareStarting: {_name}; {_downstreamContext.HttpContext.Request.Path}"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_trace_middleware_finished()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(_ => GivenAMiddlewareName())
 | 
				
			||||||
 | 
					                .And(_ => GivenAContext())
 | 
				
			||||||
 | 
					                .When(_ => WhenMiddlewareFinishedCalled())
 | 
				
			||||||
 | 
					                .Then(_ => ThenTheLogIs($"MiddlewareFinished: {_name}; {_downstreamContext.HttpContext.Response.StatusCode}"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_trace_middleware_exception()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(_ => GivenAMiddlewareName())
 | 
				
			||||||
 | 
					                .And(_ => GivenAContext())
 | 
				
			||||||
 | 
					                .And(_ => GivenAException(new Exception("oh no")))
 | 
				
			||||||
 | 
					                .When(_ => WhenMiddlewareExceptionCalled())
 | 
				
			||||||
 | 
					                .Then(_ => ThenTheLogIs($"MiddlewareException: {_name}; {_exception.Message};"))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenAException(Exception exception)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _exception = exception;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenOcelotMiddlewareStartedCalled()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _listener.OcelotMiddlewareStarted(_downstreamContext, _name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenOcelotMiddlewareFinishedCalled()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _listener.OcelotMiddlewareFinished(_downstreamContext, _name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenOcelotMiddlewareExceptionCalled()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _listener.OcelotMiddlewareException(_exception, _downstreamContext, _name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenMiddlewareStartedCalled()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _listener.OnMiddlewareStarting(_downstreamContext.HttpContext, _name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenMiddlewareFinishedCalled()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _listener.OnMiddlewareFinished(_downstreamContext.HttpContext, _name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenMiddlewareExceptionCalled()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _listener.OnMiddlewareException(_exception, _name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenAContext()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenAMiddlewareName()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _name = "name";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheLogIs(string expected)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.Verify(
 | 
				
			||||||
 | 
					                x => x.LogTrace(expected));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										75
									
								
								test/Ocelot.UnitTests/Middleware/OcelotMiddlewareTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								test/Ocelot.UnitTests/Middleware/OcelotMiddlewareTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Moq;
 | 
				
			||||||
 | 
					using Ocelot.Errors;
 | 
				
			||||||
 | 
					using Ocelot.Logging;
 | 
				
			||||||
 | 
					using Ocelot.Middleware;
 | 
				
			||||||
 | 
					using Ocelot.UnitTests.Responder;
 | 
				
			||||||
 | 
					using TestStack.BDDfy;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ocelot.UnitTests.Middleware
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OcelotMiddlewareTests
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private Mock<IOcelotLogger> _logger;
 | 
				
			||||||
 | 
					        private FakeMiddleware _middleware;
 | 
				
			||||||
 | 
					        private List<Error> _errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public OcelotMiddlewareTests()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _errors = new List<Error>();
 | 
				
			||||||
 | 
					            _logger = new Mock<IOcelotLogger>();
 | 
				
			||||||
 | 
					            _middleware = new FakeMiddleware(_logger.Object);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_error()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x => GivenAnError(new AnyError()))
 | 
				
			||||||
 | 
					                .When(x => WhenISetTheError())
 | 
				
			||||||
 | 
					                .Then(x => ThenTheErrorIsLogged(1))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_log_errors()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x => GivenAnError(new AnyError()))
 | 
				
			||||||
 | 
					                .And(x => GivenAnError(new AnyError()))
 | 
				
			||||||
 | 
					                .When(x => WhenISetTheErrors())
 | 
				
			||||||
 | 
					                .Then(x => ThenTheErrorIsLogged(2))
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenISetTheErrors()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _middleware.SetPipelineError(new DownstreamContext(new DefaultHttpContext()), _errors);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheErrorIsLogged(int times)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.Verify(x => x.LogWarning("blahh"), Times.Exactly(times));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void WhenISetTheError()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _middleware.SetPipelineError(new DownstreamContext(new DefaultHttpContext()), _errors[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenAnError(Error error)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _errors.Add(error);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class FakeMiddleware : OcelotMiddleware
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public FakeMiddleware(IOcelotLogger logger) 
 | 
				
			||||||
 | 
					            : base(logger)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -57,4 +57,8 @@
 | 
				
			|||||||
    <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
 | 
					    <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Folder Include="WebSockets\" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</Project>
 | 
					</Project>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,6 @@
 | 
				
			|||||||
using Ocelot.Middleware;
 | 
					namespace Ocelot.UnitTests.RequestId
 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Ocelot.UnitTests.RequestId
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    using Microsoft.AspNetCore.Http;
 | 
					    using Microsoft.AspNetCore.Http;
 | 
				
			||||||
    using Microsoft.Extensions.Primitives;
 | 
					 | 
				
			||||||
    using Ocelot.Infrastructure.RequestData;
 | 
					    using Ocelot.Infrastructure.RequestData;
 | 
				
			||||||
    using System;
 | 
					    using System;
 | 
				
			||||||
    using System.Collections.Generic;
 | 
					    using System.Collections.Generic;
 | 
				
			||||||
@@ -21,6 +18,7 @@ namespace Ocelot.UnitTests.RequestId
 | 
				
			|||||||
    using TestStack.BDDfy;
 | 
					    using TestStack.BDDfy;
 | 
				
			||||||
    using Xunit;
 | 
					    using Xunit;
 | 
				
			||||||
    using Ocelot.Request.Middleware;
 | 
					    using Ocelot.Request.Middleware;
 | 
				
			||||||
 | 
					    using Ocelot.Middleware;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class ReRouteRequestIdMiddlewareTests
 | 
					    public class ReRouteRequestIdMiddlewareTests
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -142,6 +140,30 @@ namespace Ocelot.UnitTests.RequestId
 | 
				
			|||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_not_update_if_global_request_id_is_same_as_re_route_request_id()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
 | 
				
			||||||
 | 
					                new ReRouteBuilder()
 | 
				
			||||||
 | 
					                    .WithDownstreamReRoute(new DownstreamReRouteBuilder()
 | 
				
			||||||
 | 
					                        .WithDownstreamPathTemplate("any old string")
 | 
				
			||||||
 | 
					                        .WithRequestIdKey("LSRequestId")
 | 
				
			||||||
 | 
					                        .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
				
			||||||
 | 
					                        .Build())
 | 
				
			||||||
 | 
					                    .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
				
			||||||
 | 
					                    .Build());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var requestId = "alreadyset";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
 | 
				
			||||||
 | 
					                .And(x => GivenTheRequestIdWasSetGlobally())
 | 
				
			||||||
 | 
					                .And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
 | 
				
			||||||
 | 
					                .When(x => x.WhenICallTheMiddleware())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenTheTraceIdIs(requestId))
 | 
				
			||||||
 | 
					                .And(x => ThenTheRequestIdIsNotUpdated())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void WhenICallTheMiddleware()
 | 
					        private void WhenICallTheMiddleware()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
 | 
					            _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
 | 
				
			||||||
@@ -159,12 +181,17 @@ namespace Ocelot.UnitTests.RequestId
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void ThenTheRequestIdIsSaved()
 | 
					        private void ThenTheRequestIdIsSaved()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _repo.Verify(x => x.Add<string>("RequestId", _value), Times.Once);
 | 
					            _repo.Verify(x => x.Add("RequestId", _value), Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenTheRequestIdIsUpdated()
 | 
					        private void ThenTheRequestIdIsUpdated()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _repo.Verify(x => x.Update<string>("RequestId", _value), Times.Once);
 | 
					            _repo.Verify(x => x.Update("RequestId", _value), Times.Once);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ThenTheRequestIdIsNotUpdated()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _repo.Verify(x => x.Update("RequestId", _value), Times.Never);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
 | 
					        private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
 | 
				
			||||||
@@ -182,15 +209,13 @@ namespace Ocelot.UnitTests.RequestId
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void ThenTheTraceIdIsAnything()
 | 
					        private void ThenTheTraceIdIsAnything()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            StringValues value;
 | 
					            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
 | 
				
			||||||
            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
 | 
					 | 
				
			||||||
            value.First().ShouldNotBeNullOrEmpty();
 | 
					            value.First().ShouldNotBeNullOrEmpty();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ThenTheTraceIdIs(string expected)
 | 
					        private void ThenTheTraceIdIs(string expected)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            StringValues value;
 | 
					            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
 | 
				
			||||||
            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
 | 
					 | 
				
			||||||
            value.First().ShouldBe(expected);
 | 
					            value.First().ShouldBe(expected);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.Responder
 | 
				
			|||||||
        public void should_return_any_errors()
 | 
					        public void should_return_any_errors()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage()))
 | 
					            this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage()))
 | 
				
			||||||
                .And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError()))
 | 
					                .And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError("/path", "GET")))
 | 
				
			||||||
                .When(x => x.WhenICallTheMiddleware())
 | 
					                .When(x => x.WhenICallTheMiddleware())
 | 
				
			||||||
                .Then(x => x.ThenThereAreNoErrors())
 | 
					                .Then(x => x.ThenThereAreNoErrors())
 | 
				
			||||||
                .BDDfy();
 | 
					                .BDDfy();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,12 +142,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
				
			|||||||
        private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
 | 
					        private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.Verify(
 | 
					            _logger.Verify(
 | 
				
			||||||
                x => x.LogError(
 | 
					                x => x.LogWarning(
 | 
				
			||||||
                    "Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
					                    "Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
				
			||||||
                Times.Once);
 | 
					                Times.Once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.Verify(
 | 
					            _logger.Verify(
 | 
				
			||||||
                x => x.LogError(
 | 
					                x => x.LogWarning(
 | 
				
			||||||
                    "Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
					                    "Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
				
			||||||
                Times.Once);
 | 
					                Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -155,12 +155,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
				
			|||||||
        private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
 | 
					        private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.Verify(
 | 
					            _logger.Verify(
 | 
				
			||||||
                x => x.LogError(
 | 
					                x => x.LogWarning(
 | 
				
			||||||
                    "Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
					                    "Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
				
			||||||
                Times.Once);
 | 
					                Times.Once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.Verify(
 | 
					            _logger.Verify(
 | 
				
			||||||
                x => x.LogError(
 | 
					                x => x.LogWarning(
 | 
				
			||||||
                    "Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
					                    "Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
 | 
				
			||||||
                Times.Once);
 | 
					                Times.Once);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user