mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 15:30:49 +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
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public AuthenticationMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory)
 | 
			
		||||
            : base(loggerFactory.CreateLogger<AuthenticationMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<AuthenticationMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
                
 | 
			
		||||
@@ -33,25 +32,22 @@ namespace Ocelot.Authentication.Middleware
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    var error = new List<Error>
 | 
			
		||||
                    {
 | 
			
		||||
                        new UnauthenticatedError(
 | 
			
		||||
                            $"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated")
 | 
			
		||||
                    };
 | 
			
		||||
                    var error = 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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Authorisation
 | 
			
		||||
@@ -32,19 +31,13 @@ namespace Ocelot.Authorisation
 | 
			
		||||
                    var authorised = values.Data.Contains(required.Value);
 | 
			
		||||
                    if (!authorised)
 | 
			
		||||
                    {
 | 
			
		||||
                        return new ErrorResponse<bool>(new List<Error>
 | 
			
		||||
                        {
 | 
			
		||||
                            new ClaimValueNotAuthorisedError(
 | 
			
		||||
                                $"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}")
 | 
			
		||||
                        });
 | 
			
		||||
                        return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
 | 
			
		||||
                                $"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}"));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return new ErrorResponse<bool>(new List<Error>
 | 
			
		||||
                        {
 | 
			
		||||
                            new UserDoesNotHaveClaimError($"user does not have claim {required.Key}")
 | 
			
		||||
                        });
 | 
			
		||||
                    return new ErrorResponse<bool>(new UserDoesNotHaveClaimError($"user does not have claim {required.Key}"));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,30 +13,29 @@
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IClaimsAuthoriser _claimsAuthoriser;
 | 
			
		||||
        private readonly IScopesAuthoriser _scopesAuthoriser;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public AuthorisationMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IClaimsAuthoriser claimsAuthoriser,
 | 
			
		||||
            IScopesAuthoriser scopesAuthoriser,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory)
 | 
			
		||||
            :base(loggerFactory.CreateLogger<AuthorisationMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _claimsAuthoriser = claimsAuthoriser;
 | 
			
		||||
            _scopesAuthoriser = scopesAuthoriser;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
                if (authorised.IsError)
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogDebug("error authorising user scopes");
 | 
			
		||||
                    Logger.LogWarning("error authorising user scopes");
 | 
			
		||||
 | 
			
		||||
                    SetPipelineError(context, authorised.Errors);
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -44,29 +43,26 @@
 | 
			
		||||
 | 
			
		||||
                if (IsAuthorised(authorised))
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogDebug("user scopes is authorised calling next authorisation checks");
 | 
			
		||||
                    Logger.LogInformation("user scopes is authorised calling next authorisation checks");
 | 
			
		||||
                }
 | 
			
		||||
                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>
 | 
			
		||||
                    {
 | 
			
		||||
                        new UnauthorisedError(
 | 
			
		||||
                            $"{context.HttpContext.User.Identity.Name} unable to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}")
 | 
			
		||||
                    });
 | 
			
		||||
                    SetPipelineError(context, new UnauthorisedError(
 | 
			
		||||
                            $"{context.HttpContext.User.Identity.Name} unable to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}"));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (IsAuthorisedRoute(context.DownstreamReRoute))
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("route is authorised");
 | 
			
		||||
                Logger.LogInformation("route is authorised");
 | 
			
		||||
 | 
			
		||||
                var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement);
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -74,22 +70,19 @@
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                }
 | 
			
		||||
                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>
 | 
			
		||||
                    {
 | 
			
		||||
                        new UnauthorisedError($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}")
 | 
			
		||||
                    });
 | 
			
		||||
                    SetPipelineError(context, new UnauthorisedError($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}"));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
using IdentityModel;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
@@ -38,11 +37,8 @@ namespace Ocelot.Authorisation
 | 
			
		||||
 | 
			
		||||
            if (matchesScopes.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<bool>(new List<Error>
 | 
			
		||||
                {
 | 
			
		||||
                     new ScopeNotAuthorisedError(
 | 
			
		||||
                         $"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'")
 | 
			
		||||
                });
 | 
			
		||||
                return new ErrorResponse<bool>(
 | 
			
		||||
                    new ScopeNotAuthorisedError($"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'"));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<bool>(true);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ namespace Ocelot.Cache.Middleware
 | 
			
		||||
    public class OutputCacheMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IOcelotCache<CachedResponse> _outputCache;
 | 
			
		||||
        private readonly IRegionCreator _regionCreator;
 | 
			
		||||
 | 
			
		||||
@@ -22,10 +21,10 @@ namespace Ocelot.Cache.Middleware
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IOcelotCache<CachedResponse> outputCache,
 | 
			
		||||
            IRegionCreator regionCreator)
 | 
			
		||||
                :base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _outputCache = outputCache;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
 | 
			
		||||
            _regionCreator = regionCreator;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -39,29 +38,29 @@ namespace Ocelot.Cache.Middleware
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
            if (cached != null)
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("cache entry exists for {downstreamUrlKey}", downstreamUrlKey);
 | 
			
		||||
                Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
 | 
			
		||||
 | 
			
		||||
                var response = CreateHttpResponseMessage(cached);
 | 
			
		||||
                SetHttpResponseMessageThisRequest(context, response);
 | 
			
		||||
 | 
			
		||||
                _logger.LogDebug("finished returned cached response for {downstreamUrlKey}", downstreamUrlKey);
 | 
			
		||||
                Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _logger.LogDebug("no resonse cached for {downstreamUrlKey}", downstreamUrlKey);
 | 
			
		||||
            Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
 | 
			
		||||
 | 
			
		||||
            await _next.Invoke(context);
 | 
			
		||||
 | 
			
		||||
            if (context.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey);
 | 
			
		||||
                Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -70,7 +69,7 @@ namespace Ocelot.Cache.Middleware
 | 
			
		||||
 | 
			
		||||
            _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)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,28 +12,27 @@ namespace Ocelot.Claims.Middleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IAddClaimsToRequest _addClaimsToRequest;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public ClaimsBuilderMiddleware(OcelotRequestDelegate next, 
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IAddClaimsToRequest addClaimsToRequest) 
 | 
			
		||||
                :base(loggerFactory.CreateLogger<ClaimsBuilderMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _addClaimsToRequest = addClaimsToRequest;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<ClaimsBuilderMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                    return;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,7 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
 | 
			
		||||
                if (claimToThing.IsError)
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogDebug("ClaimsToThingCreator.BuildAddThingsToRequest",
 | 
			
		||||
                        $"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
 | 
			
		||||
                    _logger.LogDebug($"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
                }
 | 
			
		||||
                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
 | 
			
		||||
                    {
 | 
			
		||||
                        _logger.LogError($"Unable to add DownstreamHeaderTransform {input.Key}: {input.Value}");
 | 
			
		||||
                        _logger.LogWarning($"Unable to add DownstreamHeaderTransform {input.Key}: {input.Value}");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
 
 | 
			
		||||
@@ -20,22 +20,14 @@ namespace Ocelot.Configuration.Parser
 | 
			
		||||
 | 
			
		||||
                if (instructions.Length <= 1)
 | 
			
		||||
                {
 | 
			
		||||
                    return new ErrorResponse<ClaimToThing>(
 | 
			
		||||
                        new List<Error>
 | 
			
		||||
                    {
 | 
			
		||||
                        new NoInstructionsError(SplitToken)
 | 
			
		||||
                    });
 | 
			
		||||
                    return new ErrorResponse<ClaimToThing>(new NoInstructionsError(SplitToken));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var claimMatch = _claimRegex.IsMatch(instructions[0]);
 | 
			
		||||
 | 
			
		||||
                if (!claimMatch)
 | 
			
		||||
                {
 | 
			
		||||
                    return new ErrorResponse<ClaimToThing>(
 | 
			
		||||
                        new List<Error>
 | 
			
		||||
                        {
 | 
			
		||||
                            new InstructionNotForClaimsError()
 | 
			
		||||
                        });
 | 
			
		||||
                    return new ErrorResponse<ClaimToThing>(new InstructionNotForClaimsError());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var newKey = GetIndexValue(instructions[0]);
 | 
			
		||||
@@ -53,11 +45,7 @@ namespace Ocelot.Configuration.Parser
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception exception)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<ClaimToThing>(
 | 
			
		||||
                    new List<Error>
 | 
			
		||||
                    {
 | 
			
		||||
                        new ParsingConfigurationHeaderError(exception)
 | 
			
		||||
                    });
 | 
			
		||||
                return new ErrorResponse<ClaimToThing>(new ParsingConfigurationHeaderError(exception));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -45,13 +45,13 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
        
 | 
			
		||||
        private async Task Poll()
 | 
			
		||||
        {
 | 
			
		||||
            _logger.LogDebug("Started polling consul");
 | 
			
		||||
            _logger.LogInformation("Started polling consul");
 | 
			
		||||
 | 
			
		||||
            var fileConfig = await _repo.Get();
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace Ocelot.Configuration.Repository
 | 
			
		||||
                _previousAsJson = asJson;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _logger.LogDebug("Finished polling consul");
 | 
			
		||||
            _logger.LogInformation("Finished polling consul");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,8 @@ namespace Ocelot.Configuration.Validator
 | 
			
		||||
            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 new ErrorResponse<DownstreamRoute>(new List<Error>
 | 
			
		||||
            {
 | 
			
		||||
                new UnableToFindDownstreamRouteError()
 | 
			
		||||
            });
 | 
			
		||||
            return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(path, httpMethod));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,8 @@ namespace Ocelot.DownstreamRouteFinder.Finder
 | 
			
		||||
{
 | 
			
		||||
    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.Linq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Provider;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.Finder;
 | 
			
		||||
@@ -13,7 +14,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IDownstreamRouteFinder _downstreamRouteFinder;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IOcelotConfigurationProvider _configProvider;
 | 
			
		||||
        private readonly IMultiplexer _multiplexer;
 | 
			
		||||
 | 
			
		||||
@@ -22,12 +22,12 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
			
		||||
            IDownstreamRouteFinder downstreamRouteFinder,
 | 
			
		||||
            IOcelotConfigurationProvider configProvider,
 | 
			
		||||
            IMultiplexer multiplexer)
 | 
			
		||||
                :base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _configProvider = configProvider;
 | 
			
		||||
            _multiplexer = multiplexer;
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _downstreamRouteFinder = downstreamRouteFinder;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
@@ -40,27 +40,27 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }            
 | 
			
		||||
            
 | 
			
		||||
            // todo - put this back in
 | 
			
		||||
            //// _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate);
 | 
			
		||||
            var downstreamPathTemplates = string.Join(", ", downstreamRoute.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));
 | 
			
		||||
            Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");
 | 
			
		||||
 | 
			
		||||
            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 IDownstreamPathPlaceholderReplacer _replacer;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IDownstreamPathPlaceholderReplacer replacer)
 | 
			
		||||
                :base(loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _replacer = replacer;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
@@ -34,7 +33,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -53,7 +52,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
 | 
			
		||||
                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);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IOcelotConfigurationProvider _provider;
 | 
			
		||||
        private readonly IRequestScopedDataRepository _repo;
 | 
			
		||||
 | 
			
		||||
@@ -26,11 +25,11 @@ namespace Ocelot.Errors.Middleware
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory, 
 | 
			
		||||
            IOcelotConfigurationProvider provider, 
 | 
			
		||||
            IRequestScopedDataRepository repo)
 | 
			
		||||
                : base(loggerFactory.CreateLogger<ExceptionHandlerMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _provider = provider;
 | 
			
		||||
            _repo = repo;
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
@@ -39,22 +38,22 @@ namespace Ocelot.Errors.Middleware
 | 
			
		||||
            {               
 | 
			
		||||
                await TrySetGlobalRequestId(context);
 | 
			
		||||
 | 
			
		||||
                _logger.LogDebug("ocelot pipeline started");
 | 
			
		||||
                Logger.LogDebug("ocelot pipeline started");
 | 
			
		||||
 | 
			
		||||
                await _next.Invoke(context);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("error calling middleware");
 | 
			
		||||
                Logger.LogDebug("error calling middleware");
 | 
			
		||||
 | 
			
		||||
                var message = CreateMessage(context, e);
 | 
			
		||||
 | 
			
		||||
                _logger.LogError(message, e);
 | 
			
		||||
                Logger.LogError(message, e);
 | 
			
		||||
                
 | 
			
		||||
                SetInternalServerErrorOnResponse(context);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _logger.LogDebug("ocelot pipeline finished");
 | 
			
		||||
            Logger.LogDebug("ocelot pipeline finished");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task TrySetGlobalRequestId(DownstreamContext context)
 | 
			
		||||
@@ -64,22 +63,19 @@ namespace Ocelot.Errors.Middleware
 | 
			
		||||
            //first thing is get config
 | 
			
		||||
            var configuration = await _provider.Get(); 
 | 
			
		||||
            
 | 
			
		||||
                //if error throw to catch below..
 | 
			
		||||
            if(configuration.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                //else set the request id?
 | 
			
		||||
            var key = configuration.Data.RequestId;
 | 
			
		||||
 | 
			
		||||
                StringValues upstreamRequestIds;
 | 
			
		||||
                if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out upstreamRequestIds))
 | 
			
		||||
            if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
 | 
			
		||||
            {
 | 
			
		||||
                    //todo fix looking in both places
 | 
			
		||||
                context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
 | 
			
		||||
                    _repo.Add<string>("RequestId", context.HttpContext.TraceIdentifier);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _repo.Add("RequestId", context.HttpContext.TraceIdentifier);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SetInternalServerErrorOnResponse(DownstreamContext context)
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ namespace Ocelot.Headers
 | 
			
		||||
                    
 | 
			
		||||
                    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;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@ namespace Ocelot.Headers.Middleware
 | 
			
		||||
    public class HttpHeadersTransformationMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IHttpContextRequestHeaderReplacer _preReplacer;
 | 
			
		||||
        private readonly IHttpResponseHeaderReplacer _postReplacer;
 | 
			
		||||
        private readonly IAddHeadersToResponse _addHeaders;
 | 
			
		||||
@@ -20,12 +19,12 @@ namespace Ocelot.Headers.Middleware
 | 
			
		||||
            IHttpContextRequestHeaderReplacer preReplacer,
 | 
			
		||||
            IHttpResponseHeaderReplacer postReplacer,
 | 
			
		||||
            IAddHeadersToResponse addHeaders) 
 | 
			
		||||
                :base(loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _addHeaders = addHeaders;
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _postReplacer = postReplacer;
 | 
			
		||||
            _preReplacer = preReplacer;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,34 +12,33 @@ namespace Ocelot.Headers.Middleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IAddHeadersToRequest _addHeadersToRequest;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public HttpRequestHeadersBuilderMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IAddHeadersToRequest addHeadersToRequest)  
 | 
			
		||||
                :base(loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _addHeadersToRequest = addHeadersToRequest;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                _logger.LogDebug("headers have been set on context");
 | 
			
		||||
                Logger.LogInformation("headers have been set on context");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await _next.Invoke(context);
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,7 @@
 | 
			
		||||
 | 
			
		||||
            if (splits.Length < index || index < 0)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<string>(new List<Error>
 | 
			
		||||
                {
 | 
			
		||||
                    new CannotFindClaimError($"Cannot find claim for key: {key}, delimiter: {delimiter}, index: {index}")
 | 
			
		||||
                });
 | 
			
		||||
                return new ErrorResponse<string>(new CannotFindClaimError($"Cannot find claim for key: {key}, delimiter: {delimiter}, index: {index}"));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var value = splits[index];
 | 
			
		||||
@@ -55,10 +52,7 @@
 | 
			
		||||
                return new OkResponse<string>(claim.Value);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new ErrorResponse<string>(new List<Error>
 | 
			
		||||
            {
 | 
			
		||||
                new CannotFindClaimError($"Cannot find claim for key: {key}")
 | 
			
		||||
            });
 | 
			
		||||
            return new ErrorResponse<string>(new CannotFindClaimError($"Cannot find claim for key: {key}"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Infrastructure.Extensions
 | 
			
		||||
{
 | 
			
		||||
    internal static class StringValueExtensions
 | 
			
		||||
    internal static class StringValuesExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static string GetValue(this StringValues stringValues)
 | 
			
		||||
        {
 | 
			
		||||
@@ -11,6 +11,7 @@ namespace Ocelot.Infrastructure.Extensions
 | 
			
		||||
            {
 | 
			
		||||
                return stringValues;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return stringValues.ToArray().LastOrDefault();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -24,10 +24,7 @@ namespace Ocelot.Infrastructure.RequestData
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception exception)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse(new List<Error>
 | 
			
		||||
                {
 | 
			
		||||
                    new CannotAddDataError(string.Format($"Unable to add data for key: {key}, exception: {exception.Message}"))
 | 
			
		||||
                });
 | 
			
		||||
                return new ErrorResponse(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)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse(new List<Error>
 | 
			
		||||
                {
 | 
			
		||||
                    new CannotAddDataError(string.Format($"Unable to update data for key: {key}, exception: {exception.Message}"))
 | 
			
		||||
                });
 | 
			
		||||
                return new ErrorResponse(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)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<T>(new List<Error>
 | 
			
		||||
                {
 | 
			
		||||
                    new CannotFindDataError($"Unable to find data for key: {key} because HttpContext or HttpContext.Items is null")
 | 
			
		||||
                });
 | 
			
		||||
                return new ErrorResponse<T>(new CannotFindDataError($"Unable to find data for key: {key} because HttpContext or HttpContext.Items is null"));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(_httpContextAccessor.HttpContext.Items.TryGetValue(key, out obj))
 | 
			
		||||
@@ -65,10 +56,7 @@ namespace Ocelot.Infrastructure.RequestData
 | 
			
		||||
                return new OkResponse<T>(data);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new ErrorResponse<T>(new List<Error>
 | 
			
		||||
            {
 | 
			
		||||
                new CannotFindDataError($"Unable to find data for key: {key}")
 | 
			
		||||
            });
 | 
			
		||||
            return new ErrorResponse<T>(new CannotFindDataError($"Unable to find data for key: {key}"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,12 +28,12 @@ namespace Ocelot.LoadBalancer.LoadBalancers
 | 
			
		||||
 | 
			
		||||
            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())
 | 
			
		||||
            {
 | 
			
		||||
                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)
 | 
			
		||||
 
 | 
			
		||||
@@ -9,15 +9,14 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
			
		||||
    public class LoadBalancingMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly ILoadBalancerHouse _loadBalancerHouse;
 | 
			
		||||
 | 
			
		||||
        public LoadBalancingMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            ILoadBalancerHouse loadBalancerHouse) 
 | 
			
		||||
                :base(loggerFactory.CreateLogger<LoadBalancingMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<LoadBalancingMiddleware>();
 | 
			
		||||
            _loadBalancerHouse = loadBalancerHouse;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -26,7 +25,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
			
		||||
            var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration);
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -34,7 +33,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
			
		||||
            var hostAndPort = await loadBalancer.Data.Lease();
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -52,7 +51,7 @@ namespace Ocelot.LoadBalancer.Middleware
 | 
			
		||||
            }
 | 
			
		||||
            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;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Microsoft.Extensions.Logging.Internal;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Logging
 | 
			
		||||
@@ -10,34 +9,38 @@ namespace Ocelot.Logging
 | 
			
		||||
        private readonly ILogger _logger;
 | 
			
		||||
        private readonly IRequestScopedDataRepository _scopedDataRepository;
 | 
			
		||||
 | 
			
		||||
        public string Name { get; }
 | 
			
		||||
 | 
			
		||||
        public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository, string typeName)
 | 
			
		||||
        public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository)
 | 
			
		||||
        {
 | 
			
		||||
            Name = typeName;
 | 
			
		||||
            _logger = logger;
 | 
			
		||||
            _scopedDataRepository = scopedDataRepository;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void LogTrace(string message, params object[] args)
 | 
			
		||||
        public void LogTrace(string message)
 | 
			
		||||
        {            
 | 
			
		||||
            var requestId = GetOcelotRequestId();
 | 
			
		||||
            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 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 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)
 | 
			
		||||
@@ -47,18 +50,11 @@ namespace Ocelot.Logging
 | 
			
		||||
            _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)
 | 
			
		||||
        {
 | 
			
		||||
            var requestId = GetOcelotRequestId();
 | 
			
		||||
            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()
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ namespace Ocelot.Logging
 | 
			
		||||
        public IOcelotLogger 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>
 | 
			
		||||
    public interface IOcelotLogger
 | 
			
		||||
    {
 | 
			
		||||
        void LogTrace(string message, params object[] args);
 | 
			
		||||
        void LogDebug(string message, params object[] args);
 | 
			
		||||
        void LogInformation(string message, params object[] args);
 | 
			
		||||
        void LogTrace(string message);
 | 
			
		||||
        void LogDebug(string message);
 | 
			
		||||
        void LogInformation(string message);
 | 
			
		||||
        void LogWarning(string message);
 | 
			
		||||
        void LogError(string message, Exception exception);
 | 
			
		||||
        void LogError(string message, params object[] args);
 | 
			
		||||
        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.Collections.Generic;
 | 
			
		||||
using Ocelot.Infrastructure.Extensions;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Ocelot.Requester;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Logging
 | 
			
		||||
{
 | 
			
		||||
    public class OcelotDiagnosticListener
 | 
			
		||||
    {
 | 
			
		||||
        private IServiceTracer _tracer;
 | 
			
		||||
        private IOcelotLogger _logger;
 | 
			
		||||
        private readonly IServiceTracer _tracer;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceTracer tracer)
 | 
			
		||||
        {
 | 
			
		||||
@@ -27,7 +26,7 @@ namespace Ocelot.Logging
 | 
			
		||||
        [DiagnosticName("Ocelot.MiddlewareException")]
 | 
			
		||||
        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}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -41,7 +40,7 @@ namespace Ocelot.Logging
 | 
			
		||||
        [DiagnosticName("Ocelot.MiddlewareFinished")]
 | 
			
		||||
        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}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +54,7 @@ namespace Ocelot.Logging
 | 
			
		||||
        [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
 | 
			
		||||
        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")]
 | 
			
		||||
@@ -67,16 +66,17 @@ namespace Ocelot.Logging
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
            // so sticking it here as well..I guess we need a factory for this but no idea
 | 
			
		||||
            // how to hook that into the diagnostic framework at the moment.
 | 
			
		||||
            // so sticking it here as well..I guess we need a factory for this but cba to do it at
 | 
			
		||||
            // the moment
 | 
			
		||||
            if(_tracer.GetType() == typeof(FakeServiceTracer))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var span = httpContext.GetSpan();
 | 
			
		||||
 | 
			
		||||
            if(span == null)
 | 
			
		||||
            {
 | 
			
		||||
                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()))
 | 
			
		||||
                {
 | 
			
		||||
                    spanBuilder.AsChildOf(spanContext);
 | 
			
		||||
                };
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                span = _tracer.Start(spanBuilder);        
 | 
			
		||||
                httpContext.SetSpan(span);   
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            span?.Log(LogField.CreateNew().Event(@event));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,17 +13,24 @@ namespace Ocelot.Middleware
 | 
			
		||||
    {
 | 
			
		||||
        public DownstreamContext(HttpContext httpContext)
 | 
			
		||||
        {
 | 
			
		||||
            this.HttpContext = httpContext;
 | 
			
		||||
            HttpContext = httpContext;
 | 
			
		||||
            Errors = new List<Error>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
 | 
			
		||||
 | 
			
		||||
        public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
 | 
			
		||||
        public HttpContext HttpContext { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public HttpContext HttpContext { get; }
 | 
			
		||||
 | 
			
		||||
        public DownstreamReRoute DownstreamReRoute { get; set; }
 | 
			
		||||
 | 
			
		||||
        public DownstreamRequest DownstreamRequest { get; set; }
 | 
			
		||||
 | 
			
		||||
        public HttpResponseMessage DownstreamResponse { get; set; }
 | 
			
		||||
 | 
			
		||||
        public List<Error> Errors { get;set; }
 | 
			
		||||
 | 
			
		||||
        public bool IsError => Errors.Count > 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,33 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Middleware
 | 
			
		||||
{
 | 
			
		||||
    public abstract class OcelotMiddleware
 | 
			
		||||
    {        
 | 
			
		||||
        protected OcelotMiddleware()
 | 
			
		||||
        protected OcelotMiddleware(IOcelotLogger logger)
 | 
			
		||||
        {
 | 
			
		||||
            Logger = logger;
 | 
			
		||||
            MiddlewareName = this.GetType().Name;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotLogger Logger { get; }
 | 
			
		||||
 | 
			
		||||
        public string MiddlewareName { get; }
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
                        {
 | 
			
		||||
                            Write(diagnosticListener, "Ocelot.MiddlewareException", middlewareName, context);
 | 
			
		||||
                            WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context);
 | 
			
		||||
                            throw ex;
 | 
			
		||||
                        }
 | 
			
		||||
                        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)
 | 
			
		||||
        {
 | 
			
		||||
            if (app == null)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,28 +12,27 @@ namespace Ocelot.QueryStrings.Middleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IAddQueriesToRequest _addQueriesToRequest;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public QueryStringBuilderMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IAddQueriesToRequest addQueriesToRequest) 
 | 
			
		||||
                : base(loggerFactory.CreateLogger<QueryStringBuilderMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _addQueriesToRequest = addQueriesToRequest;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<QueryStringBuilderMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                    return;
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,13 @@ namespace Ocelot.Raft
 | 
			
		||||
            using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
			
		||||
            {
 | 
			
		||||
                var json = await reader.ReadToEndAsync();
 | 
			
		||||
 | 
			
		||||
                var appendEntries = JsonConvert.DeserializeObject<AppendEntries>(json, _jsonSerialiserSettings);
 | 
			
		||||
 | 
			
		||||
                _logger.LogDebug($"{_baseSchemeUrlAndPort}/appendentries called, my state is {_node.State.GetType().FullName}");
 | 
			
		||||
 | 
			
		||||
                var appendEntriesResponse = _node.Handle(appendEntries);
 | 
			
		||||
 | 
			
		||||
                return new OkObjectResult(appendEntriesResponse);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -53,9 +57,13 @@ namespace Ocelot.Raft
 | 
			
		||||
            using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
			
		||||
            {
 | 
			
		||||
                var json = await reader.ReadToEndAsync();
 | 
			
		||||
 | 
			
		||||
                var requestVote = JsonConvert.DeserializeObject<RequestVote>(json, _jsonSerialiserSettings);
 | 
			
		||||
 | 
			
		||||
                _logger.LogDebug($"{_baseSchemeUrlAndPort}/requestvote called, my state is {_node.State.GetType().FullName}");
 | 
			
		||||
 | 
			
		||||
                var requestVoteResponse = _node.Handle(requestVote);
 | 
			
		||||
 | 
			
		||||
                return new OkObjectResult(requestVoteResponse);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -68,10 +76,15 @@ namespace Ocelot.Raft
 | 
			
		||||
                using(var reader = new StreamReader(HttpContext.Request.Body))
 | 
			
		||||
                {
 | 
			
		||||
                    var json = await reader.ReadToEndAsync();
 | 
			
		||||
 | 
			
		||||
                    var command = JsonConvert.DeserializeObject<ICommand>(json, _jsonSerialiserSettings);
 | 
			
		||||
 | 
			
		||||
                    _logger.LogDebug($"{_baseSchemeUrlAndPort}/command called, my state is {_node.State.GetType().FullName}");
 | 
			
		||||
 | 
			
		||||
                    var commandResponse = _node.Accept(command);
 | 
			
		||||
 | 
			
		||||
                    json = JsonConvert.SerializeObject(commandResponse, _jsonSerialiserSettings);
 | 
			
		||||
 | 
			
		||||
                    return StatusCode(200, json);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -14,16 +14,15 @@ namespace Ocelot.RateLimit.Middleware
 | 
			
		||||
    public class ClientRateLimitMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IRateLimitCounterHandler _counterHandler;
 | 
			
		||||
        private readonly ClientRateLimitProcessor _processor;
 | 
			
		||||
 | 
			
		||||
        public ClientRateLimitMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IRateLimitCounterHandler counterHandler)
 | 
			
		||||
                :base(loggerFactory.CreateLogger<ClientRateLimitMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<ClientRateLimitMiddleware>();
 | 
			
		||||
            _counterHandler = counterHandler;
 | 
			
		||||
            _processor = new ClientRateLimitProcessor(counterHandler);
 | 
			
		||||
        }
 | 
			
		||||
@@ -35,7 +34,7 @@ namespace Ocelot.RateLimit.Middleware
 | 
			
		||||
            // check if rate limiting is enabled
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -46,7 +45,7 @@ namespace Ocelot.RateLimit.Middleware
 | 
			
		||||
            // check white list
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -112,7 +111,8 @@ namespace Ocelot.RateLimit.Middleware
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
 
 | 
			
		||||
@@ -65,5 +65,10 @@ namespace Ocelot.Request.Middleware
 | 
			
		||||
 | 
			
		||||
            return uriBuilder.Uri.AbsoluteUri;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString() 
 | 
			
		||||
        {
 | 
			
		||||
            return ToUri();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,15 +11,14 @@ namespace Ocelot.Request.Middleware
 | 
			
		||||
    public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly Mapper.IRequestMapper _requestMapper;
 | 
			
		||||
 | 
			
		||||
        public DownstreamRequestInitialiserMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            Mapper.IRequestMapper requestMapper)
 | 
			
		||||
                :base(loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>();
 | 
			
		||||
            _requestMapper = requestMapper;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,11 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Primitives;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.Middleware;
 | 
			
		||||
using Ocelot.Request.Middleware;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.RequestId.Middleware
 | 
			
		||||
@@ -16,16 +13,15 @@ namespace Ocelot.RequestId.Middleware
 | 
			
		||||
    public class ReRouteRequestIdMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IRequestScopedDataRepository _requestScopedDataRepository;
 | 
			
		||||
 | 
			
		||||
        public ReRouteRequestIdMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory, 
 | 
			
		||||
            IRequestScopedDataRepository requestScopedDataRepository)
 | 
			
		||||
                : base(loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _requestScopedDataRepository = requestScopedDataRepository;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
            var key = context.DownstreamReRoute.RequestIdKey ?? DefaultRequestIdKey.Value;
 | 
			
		||||
 | 
			
		||||
            StringValues upstreamRequestIds;
 | 
			
		||||
            if (context.HttpContext.Request.Headers.TryGetValue(key, out upstreamRequestIds))
 | 
			
		||||
            if (context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
 | 
			
		||||
            {
 | 
			
		||||
                //set the traceidentifier
 | 
			
		||||
                context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
 | 
			
		||||
 | 
			
		||||
                //todo fix looking in both places
 | 
			
		||||
                //check if we have previous id in scoped repo
 | 
			
		||||
                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
 | 
			
		||||
                    _requestScopedDataRepository.Add<string>("PreviousRequestId", previousRequestId.Data);
 | 
			
		||||
                    _requestScopedDataRepository.Update<string>("RequestId", context.HttpContext.TraceIdentifier);
 | 
			
		||||
                    _requestScopedDataRepository.Add("PreviousRequestId", previousRequestId.Data);
 | 
			
		||||
                    _requestScopedDataRepository.Update("RequestId", context.HttpContext.TraceIdentifier);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    //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 IHttpRequester _requester;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public HttpRequesterMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IHttpRequester requester)
 | 
			
		||||
                : base(loggerFactory.CreateLogger<HttpRequesterMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _requester = requester;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<HttpRequesterMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
@@ -29,13 +28,13 @@ namespace Ocelot.Requester.Middleware
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _logger.LogDebug("setting http response message");
 | 
			
		||||
            Logger.LogDebug("setting http response message");
 | 
			
		||||
 | 
			
		||||
            context.DownstreamResponse = response.Data;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
@@ -13,7 +12,7 @@ namespace Ocelot.Requester
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceTracer _tracer;
 | 
			
		||||
        private readonly IRequestScopedDataRepository _repo;
 | 
			
		||||
        private const string prefix_spanId = "ot-spanId";
 | 
			
		||||
        private const string PrefixSpanId = "ot-spanId";
 | 
			
		||||
 | 
			
		||||
        public OcelotHttpTracingHandler(
 | 
			
		||||
            IServiceTracer tracer, 
 | 
			
		||||
@@ -37,11 +36,10 @@ namespace Ocelot.Requester
 | 
			
		||||
            HttpRequestMessage request, 
 | 
			
		||||
            CancellationToken cancellationToken)
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<string> traceIdVals = null;
 | 
			
		||||
            if (request.Headers.TryGetValues(prefix_spanId, out traceIdVals))
 | 
			
		||||
            if (request.Headers.Contains(PrefixSpanId))
 | 
			
		||||
            {
 | 
			
		||||
                request.Headers.Remove(prefix_spanId);
 | 
			
		||||
                request.Headers.TryAddWithoutValidation(prefix_spanId, span.SpanContext.SpanId);
 | 
			
		||||
                request.Headers.Remove(PrefixSpanId);
 | 
			
		||||
                request.Headers.TryAddWithoutValidation(PrefixSpanId, span.SpanContext.SpanId);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _repo.Add("TraceId", span.SpanContext.TraceId);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ using Ocelot.Middleware;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.Middleware;
 | 
			
		||||
using Ocelot.Infrastructure.Extensions;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Responder.Middleware
 | 
			
		||||
{
 | 
			
		||||
@@ -17,18 +18,17 @@ namespace Ocelot.Responder.Middleware
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IHttpResponder _responder;
 | 
			
		||||
        private readonly IErrorsToHttpStatusCodeMapper _codeMapper;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public ResponderMiddleware(OcelotRequestDelegate next, 
 | 
			
		||||
            IHttpResponder responder,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IErrorsToHttpStatusCodeMapper codeMapper
 | 
			
		||||
           )
 | 
			
		||||
            :base(loggerFactory.CreateLogger<ResponderMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _responder = responder;
 | 
			
		||||
            _codeMapper = codeMapper;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<ResponderMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
@@ -37,19 +37,13 @@ namespace Ocelot.Responder.Middleware
 | 
			
		||||
 | 
			
		||||
            if (context.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                var errors = context.Errors;
 | 
			
		||||
                _logger.LogError($"{errors.Count} pipeline errors found in {MiddlewareName}. Setting error response status code");
 | 
			
		||||
                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}");
 | 
			
		||||
                
 | 
			
		||||
                foreach(var error in errors)
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogError(error.Message);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                SetErrorResponse(context.HttpContext, errors);
 | 
			
		||||
                SetErrorResponse(context.HttpContext, context.Errors);
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,13 @@ namespace Ocelot.Responses
 | 
			
		||||
{
 | 
			
		||||
    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>();
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        public List<Error> Errors { get; private set; }
 | 
			
		||||
        public List<Error> Errors { get; }
 | 
			
		||||
 | 
			
		||||
        public bool IsError
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return Errors.Count > 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public bool IsError => Errors.Count > 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -47,7 +47,7 @@ namespace Ocelot.ServiceDiscovery.Providers
 | 
			
		||||
                }
 | 
			
		||||
                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
 | 
			
		||||
    {
 | 
			
		||||
        private OcelotRequestDelegate _next;
 | 
			
		||||
        private IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public WebSocketsProxyMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory)
 | 
			
		||||
                :base(loggerFactory.CreateLogger<WebSocketsProxyMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<WebSocketsProxyMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(DownstreamContext context)
 | 
			
		||||
 
 | 
			
		||||
@@ -37,11 +37,11 @@ namespace Ocelot.ManualTest
 | 
			
		||||
                         {
 | 
			
		||||
                             x.WithDictionaryHandle();
 | 
			
		||||
                         })
 | 
			
		||||
                         .AddOpenTracing(option =>
 | 
			
		||||
                       /*  .AddOpenTracing(option =>
 | 
			
		||||
                         {
 | 
			
		||||
                             option.CollectorUrl = "http://localhost:9618";
 | 
			
		||||
                             option.Service = "Ocelot.ManualTest";
 | 
			
		||||
                         })
 | 
			
		||||
                         })*/
 | 
			
		||||
                         .AddAdministration("/administration", "secret");
 | 
			
		||||
                })
 | 
			
		||||
                .ConfigureLogging((hostingContext, logging) =>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
  "Logging": {
 | 
			
		||||
    "IncludeScopes": false,
 | 
			
		||||
    "LogLevel": {
 | 
			
		||||
      "Default": "Error",
 | 
			
		||||
      "Default": "Trace",
 | 
			
		||||
      "System": "Error",
 | 
			
		||||
      "Microsoft": "Error"
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
        private void ThenTheLoggerIsCalledCorrectly()
 | 
			
		||||
        {
 | 
			
		||||
            _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()
 | 
			
		||||
 
 | 
			
		||||
@@ -124,7 +124,7 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
 | 
			
		||||
        private void ThenTheLoggerIsCalledCorrectly(string message)
 | 
			
		||||
        {
 | 
			
		||||
            _logger.Verify(x => x.LogError(message), Times.Once);
 | 
			
		||||
            _logger.Verify(x => x.LogWarning(message), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,3 @@
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Errors
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
@@ -15,18 +13,18 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Errors;
 | 
			
		||||
    using Ocelot.DownstreamRouteFinder.Middleware;
 | 
			
		||||
    using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
    using Ocelot.Middleware;
 | 
			
		||||
 | 
			
		||||
    public class ExceptionHandlerMiddlewareTests
 | 
			
		||||
    {
 | 
			
		||||
        bool _shouldThrowAnException = false;
 | 
			
		||||
        private Mock<IOcelotConfigurationProvider> _provider;
 | 
			
		||||
        private Mock<IRequestScopedDataRepository> _repo;
 | 
			
		||||
        bool _shouldThrowAnException;
 | 
			
		||||
        private readonly Mock<IOcelotConfigurationProvider> _provider;
 | 
			
		||||
        private readonly Mock<IRequestScopedDataRepository> _repo;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private Mock<IOcelotLogger> _logger;
 | 
			
		||||
        private ExceptionHandlerMiddleware _middleware;
 | 
			
		||||
        private DownstreamContext _downstreamContext;
 | 
			
		||||
        private readonly ExceptionHandlerMiddleware _middleware;
 | 
			
		||||
        private readonly DownstreamContext _downstreamContext;
 | 
			
		||||
        private OcelotRequestDelegate _next;
 | 
			
		||||
 | 
			
		||||
        public ExceptionHandlerMiddlewareTests()
 | 
			
		||||
@@ -59,7 +57,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(_ => WhenICallTheMiddleware())
 | 
			
		||||
                .Then(_ => ThenTheResponseIsOk())
 | 
			
		||||
                .And(_ => TheRequestIdIsNotSet())
 | 
			
		||||
                .And(_ => TheAspDotnetRequestIdIsSet())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -89,7 +87,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void ShouldNotSetRequestId()
 | 
			
		||||
        public void ShouldSetAspDotNetRequestId()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
			
		||||
 | 
			
		||||
@@ -97,7 +95,7 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
                .And(_ => GivenTheConfigurationIs(config))
 | 
			
		||||
                .When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
 | 
			
		||||
                .Then(_ => ThenTheResponseIsOk())
 | 
			
		||||
                .And(_ => TheRequestIdIsNotSet())
 | 
			
		||||
                .And(_ => TheAspDotnetRequestIdIsSet())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -146,29 +144,19 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
 | 
			
		||||
        private void GivenTheConfigReturnsError()
 | 
			
		||||
        {
 | 
			
		||||
            var config = new OcelotConfiguration(null, null, null, null);
 | 
			
		||||
 | 
			
		||||
            var response = new Ocelot.Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
 | 
			
		||||
            var response = new Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
 | 
			
		||||
            _provider
 | 
			
		||||
                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public class FakeError : Error
 | 
			
		||||
        {
 | 
			
		||||
            public FakeError() 
 | 
			
		||||
                : base("meh", OcelotErrorCode.CannotAddDataError)
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
            var response = new Ocelot.Responses.OkResponse<IOcelotConfiguration>(config);
 | 
			
		||||
            var response = new Responses.OkResponse<IOcelotConfiguration>(config);
 | 
			
		||||
            _provider
 | 
			
		||||
                .Setup(x => x.Get()).ReturnsAsync(response);
 | 
			
		||||
        }
 | 
			
		||||
@@ -193,9 +181,17 @@ namespace Ocelot.UnitTests.Errors
 | 
			
		||||
            _downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void TheRequestIdIsNotSet()
 | 
			
		||||
        private void TheAspDotnetRequestIdIsSet()
 | 
			
		||||
        {
 | 
			
		||||
            _repo.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class FakeError : Error
 | 
			
		||||
        {
 | 
			
		||||
            internal FakeError()
 | 
			
		||||
                : base("meh", OcelotErrorCode.CannotAddDataError)
 | 
			
		||||
            {
 | 
			
		||||
            _repo.Verify(x => x.Add<string>(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace Ocelot.UnitTests.Headers
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="WebSockets\" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.RequestId
 | 
			
		||||
namespace Ocelot.UnitTests.RequestId
 | 
			
		||||
{
 | 
			
		||||
    using Microsoft.AspNetCore.Http;
 | 
			
		||||
    using Microsoft.Extensions.Primitives;
 | 
			
		||||
    using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
@@ -21,6 +18,7 @@ namespace Ocelot.UnitTests.RequestId
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
    using Ocelot.Request.Middleware;
 | 
			
		||||
    using Ocelot.Middleware;
 | 
			
		||||
 | 
			
		||||
    public class ReRouteRequestIdMiddlewareTests
 | 
			
		||||
    {
 | 
			
		||||
@@ -142,6 +140,30 @@ namespace Ocelot.UnitTests.RequestId
 | 
			
		||||
                .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()
 | 
			
		||||
        {
 | 
			
		||||
            _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
 | 
			
		||||
@@ -159,12 +181,17 @@ namespace Ocelot.UnitTests.RequestId
 | 
			
		||||
 | 
			
		||||
        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()
 | 
			
		||||
        {
 | 
			
		||||
            _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)
 | 
			
		||||
@@ -182,15 +209,13 @@ namespace Ocelot.UnitTests.RequestId
 | 
			
		||||
 | 
			
		||||
        private void ThenTheTraceIdIsAnything()
 | 
			
		||||
        {
 | 
			
		||||
            StringValues value;
 | 
			
		||||
            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
 | 
			
		||||
            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
 | 
			
		||||
            value.First().ShouldNotBeNullOrEmpty();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheTraceIdIs(string expected)
 | 
			
		||||
        {
 | 
			
		||||
            StringValues value;
 | 
			
		||||
            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
 | 
			
		||||
            _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
 | 
			
		||||
            value.First().ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.Responder
 | 
			
		||||
        public void should_return_any_errors()
 | 
			
		||||
        {
 | 
			
		||||
            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())
 | 
			
		||||
                .Then(x => x.ThenThereAreNoErrors())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
 
 | 
			
		||||
@@ -142,12 +142,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
        private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
 | 
			
		||||
        {
 | 
			
		||||
            _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"),
 | 
			
		||||
                Times.Once);
 | 
			
		||||
 | 
			
		||||
            _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"),
 | 
			
		||||
                Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
@@ -155,12 +155,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
 | 
			
		||||
        private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
 | 
			
		||||
        {
 | 
			
		||||
            _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"),
 | 
			
		||||
                Times.Once);
 | 
			
		||||
 | 
			
		||||
            _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"),
 | 
			
		||||
                Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user