Merge branch 'release/5.5.0'

This commit is contained in:
Tom Pallister 2018-04-07 12:08:35 +01:00
commit 0073a6f550
61 changed files with 609 additions and 390 deletions

View File

@ -12,20 +12,19 @@ namespace Ocelot.Authentication.Middleware
public class AuthenticationMiddleware : OcelotMiddleware public class AuthenticationMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
public AuthenticationMiddleware(OcelotRequestDelegate next, public AuthenticationMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory) IOcelotLoggerFactory loggerFactory)
: base(loggerFactory.CreateLogger<AuthenticationMiddleware>())
{ {
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<AuthenticationMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (IsAuthenticatedRoute(context.DownstreamReRoute)) if (IsAuthenticatedRoute(context.DownstreamReRoute))
{ {
_logger.LogDebug($"{context.HttpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated"); Logger.LogInformation($"{context.HttpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey); var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
@ -33,25 +32,22 @@ namespace Ocelot.Authentication.Middleware
if (context.HttpContext.User.Identity.IsAuthenticated) if (context.HttpContext.User.Identity.IsAuthenticated)
{ {
_logger.LogDebug($"Client has been authenticated for {context.HttpContext.Request.Path}"); Logger.LogInformation($"Client has been authenticated for {context.HttpContext.Request.Path}");
await _next.Invoke(context); await _next.Invoke(context);
} }
else else
{ {
var error = new List<Error> var error = new UnauthenticatedError(
{ $"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated");
new UnauthenticatedError(
$"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated")
};
_logger.LogError($"Client has NOT been authenticated for {context.HttpContext.Request.Path} and pipeline error set. {error.ToErrorString()}"); Logger.LogWarning($"Client has NOT been authenticated for {context.HttpContext.Request.Path} and pipeline error set. {error}");
SetPipelineError(context, error); SetPipelineError(context, error);
} }
} }
else else
{ {
_logger.LogTrace($"No authentication needed for {context.HttpContext.Request.Path}"); Logger.LogInformation($"No authentication needed for {context.HttpContext.Request.Path}");
await _next.Invoke(context); await _next.Invoke(context);
} }

View File

@ -1,6 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Claims; using System.Security.Claims;
using Ocelot.Errors;
using Ocelot.Responses; using Ocelot.Responses;
namespace Ocelot.Authorisation namespace Ocelot.Authorisation
@ -32,19 +31,13 @@ namespace Ocelot.Authorisation
var authorised = values.Data.Contains(required.Value); var authorised = values.Data.Contains(required.Value);
if (!authorised) if (!authorised)
{ {
return new ErrorResponse<bool>(new List<Error> return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
{ $"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}"));
new ClaimValueNotAuthorisedError(
$"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}")
});
} }
} }
else else
{ {
return new ErrorResponse<bool>(new List<Error> return new ErrorResponse<bool>(new UserDoesNotHaveClaimError($"user does not have claim {required.Key}"));
{
new UserDoesNotHaveClaimError($"user does not have claim {required.Key}")
});
} }
} }

View File

@ -13,30 +13,29 @@
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IClaimsAuthoriser _claimsAuthoriser; private readonly IClaimsAuthoriser _claimsAuthoriser;
private readonly IScopesAuthoriser _scopesAuthoriser; private readonly IScopesAuthoriser _scopesAuthoriser;
private readonly IOcelotLogger _logger;
public AuthorisationMiddleware(OcelotRequestDelegate next, public AuthorisationMiddleware(OcelotRequestDelegate next,
IClaimsAuthoriser claimsAuthoriser, IClaimsAuthoriser claimsAuthoriser,
IScopesAuthoriser scopesAuthoriser, IScopesAuthoriser scopesAuthoriser,
IOcelotLoggerFactory loggerFactory) IOcelotLoggerFactory loggerFactory)
:base(loggerFactory.CreateLogger<AuthorisationMiddleware>())
{ {
_next = next; _next = next;
_claimsAuthoriser = claimsAuthoriser; _claimsAuthoriser = claimsAuthoriser;
_scopesAuthoriser = scopesAuthoriser; _scopesAuthoriser = scopesAuthoriser;
_logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (IsAuthenticatedRoute(context.DownstreamReRoute)) if (IsAuthenticatedRoute(context.DownstreamReRoute))
{ {
_logger.LogDebug("route is authenticated scopes must be checked"); Logger.LogInformation("route is authenticated scopes must be checked");
var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes); var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes);
if (authorised.IsError) if (authorised.IsError)
{ {
_logger.LogDebug("error authorising user scopes"); Logger.LogWarning("error authorising user scopes");
SetPipelineError(context, authorised.Errors); SetPipelineError(context, authorised.Errors);
return; return;
@ -44,29 +43,26 @@
if (IsAuthorised(authorised)) if (IsAuthorised(authorised))
{ {
_logger.LogDebug("user scopes is authorised calling next authorisation checks"); Logger.LogInformation("user scopes is authorised calling next authorisation checks");
} }
else else
{ {
_logger.LogDebug("user scopes is not authorised setting pipeline error"); Logger.LogWarning("user scopes is not authorised setting pipeline error");
SetPipelineError(context, new List<Error> SetPipelineError(context, new UnauthorisedError(
{ $"{context.HttpContext.User.Identity.Name} unable to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}"));
new UnauthorisedError(
$"{context.HttpContext.User.Identity.Name} unable to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}")
});
} }
} }
if (IsAuthorisedRoute(context.DownstreamReRoute)) if (IsAuthorisedRoute(context.DownstreamReRoute))
{ {
_logger.LogDebug("route is authorised"); Logger.LogInformation("route is authorised");
var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement); var authorised = _claimsAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.RouteClaimsRequirement);
if (authorised.IsError) if (authorised.IsError)
{ {
_logger.LogDebug($"Error whilst authorising {context.HttpContext.User.Identity.Name} for {context.HttpContext.User.Identity.Name}. Setting pipeline error"); Logger.LogWarning($"Error whilst authorising {context.HttpContext.User.Identity.Name}. Setting pipeline error");
SetPipelineError(context, authorised.Errors); SetPipelineError(context, authorised.Errors);
return; return;
@ -74,22 +70,19 @@
if (IsAuthorised(authorised)) if (IsAuthorised(authorised))
{ {
_logger.LogDebug($"{context.HttpContext.User.Identity.Name} has succesfully been authorised for {context.DownstreamReRoute.UpstreamPathTemplate.Value}. Calling next middleware"); Logger.LogInformation($"{context.HttpContext.User.Identity.Name} has succesfully been authorised for {context.DownstreamReRoute.UpstreamPathTemplate.Value}.");
await _next.Invoke(context); await _next.Invoke(context);
} }
else else
{ {
_logger.LogDebug($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}. Setting pipeline error"); Logger.LogWarning($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}. Setting pipeline error");
SetPipelineError(context, new List<Error> SetPipelineError(context, new UnauthorisedError($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}"));
{
new UnauthorisedError($"{context.HttpContext.User.Identity.Name} is not authorised to access {context.DownstreamReRoute.UpstreamPathTemplate.Value}")
});
} }
} }
else else
{ {
_logger.LogDebug($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised"); Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
await _next.Invoke(context); await _next.Invoke(context);
} }
} }

View File

@ -1,5 +1,4 @@
using IdentityModel; using IdentityModel;
using Ocelot.Errors;
using Ocelot.Responses; using Ocelot.Responses;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Claims; using System.Security.Claims;
@ -38,11 +37,8 @@ namespace Ocelot.Authorisation
if (matchesScopes.Count == 0) if (matchesScopes.Count == 0)
{ {
return new ErrorResponse<bool>(new List<Error> return new ErrorResponse<bool>(
{ new ScopeNotAuthorisedError($"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'"));
new ScopeNotAuthorisedError(
$"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'")
});
} }
return new OkResponse<bool>(true); return new OkResponse<bool>(true);

View File

@ -14,7 +14,6 @@ namespace Ocelot.Cache.Middleware
public class OutputCacheMiddleware : OcelotMiddleware public class OutputCacheMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IOcelotCache<CachedResponse> _outputCache; private readonly IOcelotCache<CachedResponse> _outputCache;
private readonly IRegionCreator _regionCreator; private readonly IRegionCreator _regionCreator;
@ -22,10 +21,10 @@ namespace Ocelot.Cache.Middleware
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IOcelotCache<CachedResponse> outputCache, IOcelotCache<CachedResponse> outputCache,
IRegionCreator regionCreator) IRegionCreator regionCreator)
:base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
{ {
_next = next; _next = next;
_outputCache = outputCache; _outputCache = outputCache;
_logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
_regionCreator = regionCreator; _regionCreator = regionCreator;
} }
@ -39,29 +38,29 @@ namespace Ocelot.Cache.Middleware
var downstreamUrlKey = $"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}"; var downstreamUrlKey = $"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}";
_logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey); Logger.LogDebug($"Started checking cache for {downstreamUrlKey}");
var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region); var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region);
if (cached != null) if (cached != null)
{ {
_logger.LogDebug("cache entry exists for {downstreamUrlKey}", downstreamUrlKey); Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
var response = CreateHttpResponseMessage(cached); var response = CreateHttpResponseMessage(cached);
SetHttpResponseMessageThisRequest(context, response); SetHttpResponseMessageThisRequest(context, response);
_logger.LogDebug("finished returned cached response for {downstreamUrlKey}", downstreamUrlKey); Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
return; return;
} }
_logger.LogDebug("no resonse cached for {downstreamUrlKey}", downstreamUrlKey); Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
await _next.Invoke(context); await _next.Invoke(context);
if (context.IsError) if (context.IsError)
{ {
_logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey); Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
return; return;
} }
@ -70,7 +69,7 @@ namespace Ocelot.Cache.Middleware
_outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region); _outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region);
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey); Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
} }
private void SetHttpResponseMessageThisRequest(DownstreamContext context, HttpResponseMessage response) private void SetHttpResponseMessageThisRequest(DownstreamContext context, HttpResponseMessage response)

View File

@ -12,28 +12,27 @@ namespace Ocelot.Claims.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IAddClaimsToRequest _addClaimsToRequest; private readonly IAddClaimsToRequest _addClaimsToRequest;
private readonly IOcelotLogger _logger;
public ClaimsBuilderMiddleware(OcelotRequestDelegate next, public ClaimsBuilderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IAddClaimsToRequest addClaimsToRequest) IAddClaimsToRequest addClaimsToRequest)
:base(loggerFactory.CreateLogger<ClaimsBuilderMiddleware>())
{ {
_next = next; _next = next;
_addClaimsToRequest = addClaimsToRequest; _addClaimsToRequest = addClaimsToRequest;
_logger = loggerFactory.CreateLogger<ClaimsBuilderMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (context.DownstreamReRoute.ClaimsToClaims.Any()) if (context.DownstreamReRoute.ClaimsToClaims.Any())
{ {
_logger.LogDebug("this route has instructions to convert claims to other claims"); Logger.LogDebug("this route has instructions to convert claims to other claims");
var result = _addClaimsToRequest.SetClaimsOnContext(context.DownstreamReRoute.ClaimsToClaims, context.HttpContext); var result = _addClaimsToRequest.SetClaimsOnContext(context.DownstreamReRoute.ClaimsToClaims, context.HttpContext);
if (result.IsError) if (result.IsError)
{ {
_logger.LogDebug("error converting claims to other claims, setting pipeline error"); Logger.LogDebug("error converting claims to other claims, setting pipeline error");
SetPipelineError(context, result.Errors); SetPipelineError(context, result.Errors);
return; return;

View File

@ -26,8 +26,7 @@ namespace Ocelot.Configuration.Creator
if (claimToThing.IsError) if (claimToThing.IsError)
{ {
_logger.LogDebug("ClaimsToThingCreator.BuildAddThingsToRequest", _logger.LogDebug($"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
$"Unable to extract configuration for key: {input.Key} and value: {input.Value} your configuration file is incorrect");
} }
else else
{ {

View File

@ -32,7 +32,7 @@ namespace Ocelot.Configuration.Creator
} }
else else
{ {
_logger.LogError($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}"); _logger.LogWarning($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
} }
} }
@ -50,7 +50,7 @@ namespace Ocelot.Configuration.Creator
} }
else else
{ {
_logger.LogError($"Unable to add DownstreamHeaderTransform {input.Key}: {input.Value}"); _logger.LogWarning($"Unable to add DownstreamHeaderTransform {input.Key}: {input.Value}");
} }
} }
else else

View File

@ -20,22 +20,14 @@ namespace Ocelot.Configuration.Parser
if (instructions.Length <= 1) if (instructions.Length <= 1)
{ {
return new ErrorResponse<ClaimToThing>( return new ErrorResponse<ClaimToThing>(new NoInstructionsError(SplitToken));
new List<Error>
{
new NoInstructionsError(SplitToken)
});
} }
var claimMatch = _claimRegex.IsMatch(instructions[0]); var claimMatch = _claimRegex.IsMatch(instructions[0]);
if (!claimMatch) if (!claimMatch)
{ {
return new ErrorResponse<ClaimToThing>( return new ErrorResponse<ClaimToThing>(new InstructionNotForClaimsError());
new List<Error>
{
new InstructionNotForClaimsError()
});
} }
var newKey = GetIndexValue(instructions[0]); var newKey = GetIndexValue(instructions[0]);
@ -53,11 +45,7 @@ namespace Ocelot.Configuration.Parser
} }
catch (Exception exception) catch (Exception exception)
{ {
return new ErrorResponse<ClaimToThing>( return new ErrorResponse<ClaimToThing>(new ParsingConfigurationHeaderError(exception));
new List<Error>
{
new ParsingConfigurationHeaderError(exception)
});
} }
} }

View File

@ -45,13 +45,13 @@ namespace Ocelot.Configuration.Repository
private async Task Poll() private async Task Poll()
{ {
_logger.LogDebug("Started polling consul"); _logger.LogInformation("Started polling consul");
var fileConfig = await _repo.Get(); var fileConfig = await _repo.Get();
if(fileConfig.IsError) if(fileConfig.IsError)
{ {
_logger.LogDebug($"error geting file config, errors are {string.Join(",", fileConfig.Errors.Select(x => x.Message))}"); _logger.LogWarning($"error geting file config, errors are {string.Join(",", fileConfig.Errors.Select(x => x.Message))}");
return; return;
} }
@ -63,7 +63,7 @@ namespace Ocelot.Configuration.Repository
_previousAsJson = asJson; _previousAsJson = asJson;
} }
_logger.LogDebug("Finished polling consul"); _logger.LogInformation("Finished polling consul");
} }
/// <summary> /// <summary>

View File

@ -17,8 +17,8 @@ namespace Ocelot.Configuration.Validator
Errors = errors; Errors = errors;
} }
public bool IsError { get; private set; } public bool IsError { get; }
public List<Error> Errors { get; private set; } public List<Error> Errors { get; }
} }
} }

View File

@ -44,10 +44,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption); return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
} }
return new ErrorResponse<DownstreamRoute>(new List<Error> return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(path, httpMethod));
{
new UnableToFindDownstreamRouteError()
});
} }
private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost) private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)

View File

@ -4,7 +4,8 @@ namespace Ocelot.DownstreamRouteFinder.Finder
{ {
public class UnableToFindDownstreamRouteError : Error public class UnableToFindDownstreamRouteError : Error
{ {
public UnableToFindDownstreamRouteError() : base("UnableToFindDownstreamRouteError", OcelotErrorCode.UnableToFindDownstreamRouteError) public UnableToFindDownstreamRouteError(string path, string httpVerb)
: base($"Unable to find downstream route for path: {path}, verb: {httpVerb}", OcelotErrorCode.UnableToFindDownstreamRouteError)
{ {
} }
} }

View File

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Provider; using Ocelot.Configuration.Provider;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
@ -13,7 +14,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IDownstreamRouteFinder _downstreamRouteFinder; private readonly IDownstreamRouteFinder _downstreamRouteFinder;
private readonly IOcelotLogger _logger;
private readonly IOcelotConfigurationProvider _configProvider; private readonly IOcelotConfigurationProvider _configProvider;
private readonly IMultiplexer _multiplexer; private readonly IMultiplexer _multiplexer;
@ -22,12 +22,12 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
IDownstreamRouteFinder downstreamRouteFinder, IDownstreamRouteFinder downstreamRouteFinder,
IOcelotConfigurationProvider configProvider, IOcelotConfigurationProvider configProvider,
IMultiplexer multiplexer) IMultiplexer multiplexer)
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
{ {
_configProvider = configProvider; _configProvider = configProvider;
_multiplexer = multiplexer; _multiplexer = multiplexer;
_next = next; _next = next;
_downstreamRouteFinder = downstreamRouteFinder; _downstreamRouteFinder = downstreamRouteFinder;
_logger = loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
@ -40,27 +40,27 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
if (configuration.IsError) if (configuration.IsError)
{ {
_logger.LogError($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}"); Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
SetPipelineError(context, configuration.Errors); SetPipelineError(context, configuration.Errors);
return; return;
} }
context.ServiceProviderConfiguration = configuration.Data.ServiceProviderConfiguration; context.ServiceProviderConfiguration = configuration.Data.ServiceProviderConfiguration;
_logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath); Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.HttpContext.Request.Method, configuration.Data, upstreamHost); var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.HttpContext.Request.Method, configuration.Data, upstreamHost);
if (downstreamRoute.IsError) if (downstreamRoute.IsError)
{ {
_logger.LogError($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}"); Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
SetPipelineError(context, downstreamRoute.Errors); SetPipelineError(context, downstreamRoute.Errors);
return; return;
} }
// todo - put this back in var downstreamPathTemplates = string.Join(", ", downstreamRoute.Data.ReRoute.DownstreamReRoute.Select(r => r.DownstreamPathTemplate.Value));
//// _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate); Logger.LogDebug($"downstream templates are {downstreamPathTemplates}");
context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues; context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;

View File

@ -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);
}
}
*/

View File

@ -16,15 +16,14 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IDownstreamPathPlaceholderReplacer _replacer; private readonly IDownstreamPathPlaceholderReplacer _replacer;
private readonly IOcelotLogger _logger;
public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next, public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IDownstreamPathPlaceholderReplacer replacer) IDownstreamPathPlaceholderReplacer replacer)
:base(loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>())
{ {
_next = next; _next = next;
_replacer = replacer; _replacer = replacer;
_logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
@ -34,7 +33,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
if (dsPath.IsError) if (dsPath.IsError)
{ {
_logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error"); Logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
SetPipelineError(context, dsPath.Errors); SetPipelineError(context, dsPath.Errors);
return; return;
@ -53,7 +52,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
context.DownstreamRequest.AbsolutePath = dsPath.Data.Value; context.DownstreamRequest.AbsolutePath = dsPath.Data.Value;
} }
_logger.LogDebug("downstream url is {context.DownstreamRequest}", context.DownstreamRequest); Logger.LogDebug($"Downstream url is {context.DownstreamRequest}");
await _next.Invoke(context); await _next.Invoke(context);
} }

View File

@ -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));
}
}
}
*/

View File

@ -18,7 +18,6 @@ namespace Ocelot.Errors.Middleware
public class ExceptionHandlerMiddleware : OcelotMiddleware public class ExceptionHandlerMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IOcelotConfigurationProvider _provider; private readonly IOcelotConfigurationProvider _provider;
private readonly IRequestScopedDataRepository _repo; private readonly IRequestScopedDataRepository _repo;
@ -26,11 +25,11 @@ namespace Ocelot.Errors.Middleware
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IOcelotConfigurationProvider provider, IOcelotConfigurationProvider provider,
IRequestScopedDataRepository repo) IRequestScopedDataRepository repo)
: base(loggerFactory.CreateLogger<ExceptionHandlerMiddleware>())
{ {
_provider = provider; _provider = provider;
_repo = repo; _repo = repo;
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
@ -39,47 +38,44 @@ namespace Ocelot.Errors.Middleware
{ {
await TrySetGlobalRequestId(context); await TrySetGlobalRequestId(context);
_logger.LogDebug("ocelot pipeline started"); Logger.LogDebug("ocelot pipeline started");
await _next.Invoke(context); await _next.Invoke(context);
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogDebug("error calling middleware"); Logger.LogDebug("error calling middleware");
var message = CreateMessage(context, e); var message = CreateMessage(context, e);
_logger.LogError(message, e); Logger.LogError(message, e);
SetInternalServerErrorOnResponse(context); SetInternalServerErrorOnResponse(context);
} }
_logger.LogDebug("ocelot pipeline finished"); Logger.LogDebug("ocelot pipeline finished");
} }
private async Task TrySetGlobalRequestId(DownstreamContext context) private async Task TrySetGlobalRequestId(DownstreamContext context)
{ {
//try and get the global request id and set it for logs... //try and get the global request id and set it for logs...
//should this basically be immutable per request...i guess it should! //should this basically be immutable per request...i guess it should!
//first thing is get config //first thing is get config
var configuration = await _provider.Get(); var configuration = await _provider.Get();
//if error throw to catch below.. if(configuration.IsError)
if(configuration.IsError) {
{ throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
}
//else set the request id?
var key = configuration.Data.RequestId;
StringValues upstreamRequestIds;
if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out upstreamRequestIds))
{
//todo fix looking in both places
context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
_repo.Add<string>("RequestId", context.HttpContext.TraceIdentifier);
} }
var key = configuration.Data.RequestId;
if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
{
context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
}
_repo.Add("RequestId", context.HttpContext.TraceIdentifier);
} }
private void SetInternalServerErrorOnResponse(DownstreamContext context) private void SetInternalServerErrorOnResponse(DownstreamContext context)

View File

@ -27,7 +27,7 @@ namespace Ocelot.Headers
if(value.IsError) if(value.IsError)
{ {
_logger.LogError($"Unable to add header to response {add.Key}: {add.Value}"); _logger.LogWarning($"Unable to add header to response {add.Key}: {add.Value}");
continue; continue;
} }

View File

@ -10,7 +10,6 @@ namespace Ocelot.Headers.Middleware
public class HttpHeadersTransformationMiddleware : OcelotMiddleware public class HttpHeadersTransformationMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IHttpContextRequestHeaderReplacer _preReplacer; private readonly IHttpContextRequestHeaderReplacer _preReplacer;
private readonly IHttpResponseHeaderReplacer _postReplacer; private readonly IHttpResponseHeaderReplacer _postReplacer;
private readonly IAddHeadersToResponse _addHeaders; private readonly IAddHeadersToResponse _addHeaders;
@ -20,12 +19,12 @@ namespace Ocelot.Headers.Middleware
IHttpContextRequestHeaderReplacer preReplacer, IHttpContextRequestHeaderReplacer preReplacer,
IHttpResponseHeaderReplacer postReplacer, IHttpResponseHeaderReplacer postReplacer,
IAddHeadersToResponse addHeaders) IAddHeadersToResponse addHeaders)
:base(loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>())
{ {
_addHeaders = addHeaders; _addHeaders = addHeaders;
_next = next; _next = next;
_postReplacer = postReplacer; _postReplacer = postReplacer;
_preReplacer = preReplacer; _preReplacer = preReplacer;
_logger = loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)

View File

@ -12,34 +12,33 @@ namespace Ocelot.Headers.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IAddHeadersToRequest _addHeadersToRequest; private readonly IAddHeadersToRequest _addHeadersToRequest;
private readonly IOcelotLogger _logger;
public HttpRequestHeadersBuilderMiddleware(OcelotRequestDelegate next, public HttpRequestHeadersBuilderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IAddHeadersToRequest addHeadersToRequest) IAddHeadersToRequest addHeadersToRequest)
:base(loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>())
{ {
_next = next; _next = next;
_addHeadersToRequest = addHeadersToRequest; _addHeadersToRequest = addHeadersToRequest;
_logger = loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (context.DownstreamReRoute.ClaimsToHeaders.Any()) if (context.DownstreamReRoute.ClaimsToHeaders.Any())
{ {
_logger.LogDebug($"{ context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers"); Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.ClaimsToHeaders, context.HttpContext.User.Claims, context.DownstreamRequest); var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.ClaimsToHeaders, context.HttpContext.User.Claims, context.DownstreamRequest);
if (response.IsError) if (response.IsError)
{ {
_logger.LogDebug("Error setting headers on context, setting pipeline error"); Logger.LogWarning("Error setting headers on context, setting pipeline error");
SetPipelineError(context, response.Errors); SetPipelineError(context, response.Errors);
return; return;
} }
_logger.LogDebug("headers have been set on context"); Logger.LogInformation("headers have been set on context");
} }
await _next.Invoke(context); await _next.Invoke(context);

View File

@ -26,10 +26,7 @@
if (splits.Length < index || index < 0) if (splits.Length < index || index < 0)
{ {
return new ErrorResponse<string>(new List<Error> return new ErrorResponse<string>(new CannotFindClaimError($"Cannot find claim for key: {key}, delimiter: {delimiter}, index: {index}"));
{
new CannotFindClaimError($"Cannot find claim for key: {key}, delimiter: {delimiter}, index: {index}")
});
} }
var value = splits[index]; var value = splits[index];
@ -55,10 +52,7 @@
return new OkResponse<string>(claim.Value); return new OkResponse<string>(claim.Value);
} }
return new ErrorResponse<string>(new List<Error> return new ErrorResponse<string>(new CannotFindClaimError($"Cannot find claim for key: {key}"));
{
new CannotFindClaimError($"Cannot find claim for key: {key}")
});
} }
} }
} }

View File

@ -3,7 +3,7 @@ using System.Linq;
namespace Ocelot.Infrastructure.Extensions namespace Ocelot.Infrastructure.Extensions
{ {
internal static class StringValueExtensions internal static class StringValuesExtensions
{ {
public static string GetValue(this StringValues stringValues) public static string GetValue(this StringValues stringValues)
{ {
@ -11,6 +11,7 @@ namespace Ocelot.Infrastructure.Extensions
{ {
return stringValues; return stringValues;
} }
return stringValues.ToArray().LastOrDefault(); return stringValues.ToArray().LastOrDefault();
} }
} }

View File

@ -24,10 +24,7 @@ namespace Ocelot.Infrastructure.RequestData
} }
catch (Exception exception) catch (Exception exception)
{ {
return new ErrorResponse(new List<Error> return new ErrorResponse(new CannotAddDataError(string.Format($"Unable to add data for key: {key}, exception: {exception.Message}")));
{
new CannotAddDataError(string.Format($"Unable to add data for key: {key}, exception: {exception.Message}"))
});
} }
} }
@ -40,10 +37,7 @@ namespace Ocelot.Infrastructure.RequestData
} }
catch (Exception exception) catch (Exception exception)
{ {
return new ErrorResponse(new List<Error> return new ErrorResponse(new CannotAddDataError(string.Format($"Unable to update data for key: {key}, exception: {exception.Message}")));
{
new CannotAddDataError(string.Format($"Unable to update data for key: {key}, exception: {exception.Message}"))
});
} }
} }
@ -53,10 +47,7 @@ namespace Ocelot.Infrastructure.RequestData
if(_httpContextAccessor.HttpContext == null || _httpContextAccessor.HttpContext.Items == null) if(_httpContextAccessor.HttpContext == null || _httpContextAccessor.HttpContext.Items == null)
{ {
return new ErrorResponse<T>(new List<Error> return new ErrorResponse<T>(new CannotFindDataError($"Unable to find data for key: {key} because HttpContext or HttpContext.Items is null"));
{
new CannotFindDataError($"Unable to find data for key: {key} because HttpContext or HttpContext.Items is null")
});
} }
if(_httpContextAccessor.HttpContext.Items.TryGetValue(key, out obj)) if(_httpContextAccessor.HttpContext.Items.TryGetValue(key, out obj))
@ -65,10 +56,7 @@ namespace Ocelot.Infrastructure.RequestData
return new OkResponse<T>(data); return new OkResponse<T>(data);
} }
return new ErrorResponse<T>(new List<Error> return new ErrorResponse<T>(new CannotFindDataError($"Unable to find data for key: {key}"));
{
new CannotFindDataError($"Unable to find data for key: {key}")
});
} }
} }
} }

View File

@ -28,12 +28,12 @@ namespace Ocelot.LoadBalancer.LoadBalancers
if (services == null) if (services == null)
{ {
return new ErrorResponse<ServiceHostAndPort>(new List<Error>() { new ServicesAreNullError($"services were null for {_serviceName}") }); return new ErrorResponse<ServiceHostAndPort>(new ServicesAreNullError($"services were null for {_serviceName}") );
} }
if (!services.Any()) if (!services.Any())
{ {
return new ErrorResponse<ServiceHostAndPort>(new List<Error>() { new ServicesAreEmptyError($"services were empty for {_serviceName}") }); return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError($"services were empty for {_serviceName}"));
} }
lock(_syncLock) lock(_syncLock)

View File

@ -9,15 +9,14 @@ namespace Ocelot.LoadBalancer.Middleware
public class LoadBalancingMiddleware : OcelotMiddleware public class LoadBalancingMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly ILoadBalancerHouse _loadBalancerHouse; private readonly ILoadBalancerHouse _loadBalancerHouse;
public LoadBalancingMiddleware(OcelotRequestDelegate next, public LoadBalancingMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
ILoadBalancerHouse loadBalancerHouse) ILoadBalancerHouse loadBalancerHouse)
:base(loggerFactory.CreateLogger<LoadBalancingMiddleware>())
{ {
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<LoadBalancingMiddleware>();
_loadBalancerHouse = loadBalancerHouse; _loadBalancerHouse = loadBalancerHouse;
} }
@ -26,7 +25,7 @@ namespace Ocelot.LoadBalancer.Middleware
var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration); var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration);
if(loadBalancer.IsError) if(loadBalancer.IsError)
{ {
_logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error"); Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
SetPipelineError(context, loadBalancer.Errors); SetPipelineError(context, loadBalancer.Errors);
return; return;
} }
@ -34,7 +33,7 @@ namespace Ocelot.LoadBalancer.Middleware
var hostAndPort = await loadBalancer.Data.Lease(); var hostAndPort = await loadBalancer.Data.Lease();
if(hostAndPort.IsError) if(hostAndPort.IsError)
{ {
_logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error"); Logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
SetPipelineError(context, hostAndPort.Errors); SetPipelineError(context, hostAndPort.Errors);
return; return;
} }
@ -52,7 +51,7 @@ namespace Ocelot.LoadBalancer.Middleware
} }
catch (Exception) catch (Exception)
{ {
_logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler"); Logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
throw; throw;
} }
finally finally

View File

@ -1,6 +1,5 @@
using System; using System;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Internal;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
namespace Ocelot.Logging namespace Ocelot.Logging
@ -10,34 +9,38 @@ namespace Ocelot.Logging
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IRequestScopedDataRepository _scopedDataRepository; private readonly IRequestScopedDataRepository _scopedDataRepository;
public string Name { get; } public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository)
public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository, string typeName)
{ {
Name = typeName;
_logger = logger; _logger = logger;
_scopedDataRepository = scopedDataRepository; _scopedDataRepository = scopedDataRepository;
} }
public void LogTrace(string message, params object[] args) public void LogTrace(string message)
{ {
var requestId = GetOcelotRequestId(); var requestId = GetOcelotRequestId();
var previousRequestId = GetOcelotPreviousRequestId(); var previousRequestId = GetOcelotPreviousRequestId();
_logger.LogTrace("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, new FormattedLogValues(message, args).ToString()); _logger.LogTrace("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
} }
public void LogDebug(string message, params object[] args) public void LogDebug(string message)
{ {
var requestId = GetOcelotRequestId(); var requestId = GetOcelotRequestId();
var previousRequestId = GetOcelotPreviousRequestId(); var previousRequestId = GetOcelotPreviousRequestId();
_logger.LogDebug("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, new FormattedLogValues(message, args).ToString()); _logger.LogDebug("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
} }
public void LogInformation(string message, params object[] args) public void LogInformation(string message)
{ {
var requestId = GetOcelotRequestId(); var requestId = GetOcelotRequestId();
var previousRequestId = GetOcelotPreviousRequestId(); var previousRequestId = GetOcelotPreviousRequestId();
_logger.LogInformation("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, new FormattedLogValues(message, args).ToString()); _logger.LogInformation("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
}
public void LogWarning(string message)
{
var requestId = GetOcelotRequestId();
var previousRequestId = GetOcelotPreviousRequestId();
_logger.LogWarning("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
} }
public void LogError(string message, Exception exception) public void LogError(string message, Exception exception)
@ -47,18 +50,11 @@ namespace Ocelot.Logging
_logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception); _logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception);
} }
public void LogError(string message, params object[] args)
{
var requestId = GetOcelotRequestId();
var previousRequestId = GetOcelotPreviousRequestId();
_logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, new FormattedLogValues(message, args).ToString());
}
public void LogCritical(string message, Exception exception) public void LogCritical(string message, Exception exception)
{ {
var requestId = GetOcelotRequestId(); var requestId = GetOcelotRequestId();
var previousRequestId = GetOcelotPreviousRequestId(); var previousRequestId = GetOcelotPreviousRequestId();
_logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message); _logger.LogCritical("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception);
} }
private string GetOcelotRequestId() private string GetOcelotRequestId()

View File

@ -17,7 +17,7 @@ namespace Ocelot.Logging
public IOcelotLogger CreateLogger<T>() public IOcelotLogger CreateLogger<T>()
{ {
var logger = _loggerFactory.CreateLogger<T>(); var logger = _loggerFactory.CreateLogger<T>();
return new AspDotNetLogger(logger, _scopedDataRepository, typeof(T).Name); return new AspDotNetLogger(logger, _scopedDataRepository);
} }
} }
} }

View File

@ -7,16 +7,11 @@ namespace Ocelot.Logging
/// </summary> /// </summary>
public interface IOcelotLogger public interface IOcelotLogger
{ {
void LogTrace(string message, params object[] args); void LogTrace(string message);
void LogDebug(string message, params object[] args); void LogDebug(string message);
void LogInformation(string message, params object[] args); void LogInformation(string message);
void LogWarning(string message);
void LogError(string message, Exception exception); void LogError(string message, Exception exception);
void LogError(string message, params object[] args);
void LogCritical(string message, Exception exception); void LogCritical(string message, Exception exception);
/// <summary>
/// The name of the type the logger has been built for.
/// </summary>
string Name { get; }
} }
} }

View File

@ -8,15 +8,14 @@ using Butterfly.Client.Tracing;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Ocelot.Infrastructure.Extensions; using Ocelot.Infrastructure.Extensions;
using Microsoft.Extensions.Logging;
using Ocelot.Requester; using Ocelot.Requester;
namespace Ocelot.Logging namespace Ocelot.Logging
{ {
public class OcelotDiagnosticListener public class OcelotDiagnosticListener
{ {
private IServiceTracer _tracer; private readonly IServiceTracer _tracer;
private IOcelotLogger _logger; private readonly IOcelotLogger _logger;
public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceTracer tracer) public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceTracer tracer)
{ {
@ -27,7 +26,7 @@ namespace Ocelot.Logging
[DiagnosticName("Ocelot.MiddlewareException")] [DiagnosticName("Ocelot.MiddlewareException")]
public virtual void OcelotMiddlewareException(Exception exception, DownstreamContext context, string name) public virtual void OcelotMiddlewareException(Exception exception, DownstreamContext context, string name)
{ {
_logger.LogTrace($"Ocelot.MiddlewareException: {name}; {exception.Message}"); _logger.LogTrace($"Ocelot.MiddlewareException: {name}; {exception.Message};");
Event(context.HttpContext, $"Ocelot.MiddlewareStarted: {name}; {context.HttpContext.Request.Path}"); Event(context.HttpContext, $"Ocelot.MiddlewareStarted: {name}; {context.HttpContext.Request.Path}");
} }
@ -41,7 +40,7 @@ namespace Ocelot.Logging
[DiagnosticName("Ocelot.MiddlewareFinished")] [DiagnosticName("Ocelot.MiddlewareFinished")]
public virtual void OcelotMiddlewareFinished(DownstreamContext context, string name) public virtual void OcelotMiddlewareFinished(DownstreamContext context, string name)
{ {
_logger.LogTrace($"OcelotMiddlewareFinished: {name}; {context.HttpContext.Request.Path}"); _logger.LogTrace($"Ocelot.MiddlewareFinished: {name}; {context.HttpContext.Request.Path}");
Event(context.HttpContext, $"OcelotMiddlewareFinished: {name}; {context.HttpContext.Request.Path}"); Event(context.HttpContext, $"OcelotMiddlewareFinished: {name}; {context.HttpContext.Request.Path}");
} }
@ -55,7 +54,7 @@ namespace Ocelot.Logging
[DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")] [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
public virtual void OnMiddlewareException(Exception exception, string name) public virtual void OnMiddlewareException(Exception exception, string name)
{ {
_logger.LogTrace($"MiddlewareException: {name}; {exception.Message}"); _logger.LogTrace($"MiddlewareException: {name}; {exception.Message};");
} }
[DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")] [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")]
@ -67,16 +66,17 @@ namespace Ocelot.Logging
private void Event(HttpContext httpContext, string @event) private void Event(HttpContext httpContext, string @event)
{ {
// Hack - if the user isnt using tracing the code gets here and will blow up on // todo - if the user isnt using tracing the code gets here and will blow up on
// _tracer.Tracer.TryExtract. We already use the fake tracer for another scenario // _tracer.Tracer.TryExtract. We already use the fake tracer for another scenario
// so sticking it here as well..I guess we need a factory for this but no idea // so sticking it here as well..I guess we need a factory for this but cba to do it at
// how to hook that into the diagnostic framework at the moment. // the moment
if(_tracer.GetType() == typeof(FakeServiceTracer)) if(_tracer.GetType() == typeof(FakeServiceTracer))
{ {
return; return;
} }
var span = httpContext.GetSpan(); var span = httpContext.GetSpan();
if(span == null) if(span == null)
{ {
var spanBuilder = new SpanBuilder($"server {httpContext.Request.Method} {httpContext.Request.Path}"); var spanBuilder = new SpanBuilder($"server {httpContext.Request.Method} {httpContext.Request.Path}");
@ -84,10 +84,12 @@ namespace Ocelot.Logging
c => c.Select(x => new KeyValuePair<string, string>(x.Key, x.Value.GetValue())).GetEnumerator())) c => c.Select(x => new KeyValuePair<string, string>(x.Key, x.Value.GetValue())).GetEnumerator()))
{ {
spanBuilder.AsChildOf(spanContext); spanBuilder.AsChildOf(spanContext);
}; }
span = _tracer.Start(spanBuilder); span = _tracer.Start(spanBuilder);
httpContext.SetSpan(span); httpContext.SetSpan(span);
} }
span?.Log(LogField.CreateNew().Event(@event)); span?.Log(LogField.CreateNew().Event(@event));
} }
} }

View File

@ -13,17 +13,24 @@ namespace Ocelot.Middleware
{ {
public DownstreamContext(HttpContext httpContext) public DownstreamContext(HttpContext httpContext)
{ {
this.HttpContext = httpContext; HttpContext = httpContext;
Errors = new List<Error>(); Errors = new List<Error>();
} }
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; } public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;} public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
public HttpContext HttpContext { get; private set; }
public HttpContext HttpContext { get; }
public DownstreamReRoute DownstreamReRoute { get; set; } public DownstreamReRoute DownstreamReRoute { get; set; }
public DownstreamRequest DownstreamRequest { get; set; } public DownstreamRequest DownstreamRequest { get; set; }
public HttpResponseMessage DownstreamResponse { get; set; } public HttpResponseMessage DownstreamResponse { get; set; }
public List<Error> Errors { get;set; } public List<Error> Errors { get;set; }
public bool IsError => Errors.Count > 0; public bool IsError => Errors.Count > 0;
} }
} }

View File

@ -1,20 +1,33 @@
using System.Collections.Generic; using System.Collections.Generic;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.Logging;
namespace Ocelot.Middleware namespace Ocelot.Middleware
{ {
public abstract class OcelotMiddleware public abstract class OcelotMiddleware
{ {
protected OcelotMiddleware() protected OcelotMiddleware(IOcelotLogger logger)
{ {
Logger = logger;
MiddlewareName = this.GetType().Name; MiddlewareName = this.GetType().Name;
} }
public IOcelotLogger Logger { get; }
public string MiddlewareName { get; } public string MiddlewareName { get; }
public void SetPipelineError(DownstreamContext context, List<Error> errors) public void SetPipelineError(DownstreamContext context, List<Error> errors)
{ {
context.Errors = errors; foreach(var error in errors)
{
SetPipelineError(context, error);
}
}
public void SetPipelineError(DownstreamContext context, Error error)
{
Logger.LogWarning(error.Message);
context.Errors.Add(error);
} }
} }
} }

View File

@ -88,7 +88,7 @@ namespace Ocelot.Middleware.Pipeline
} }
catch(Exception ex) catch(Exception ex)
{ {
Write(diagnosticListener, "Ocelot.MiddlewareException", middlewareName, context); WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context);
throw ex; throw ex;
} }
finally finally
@ -123,6 +123,14 @@ namespace Ocelot.Middleware.Pipeline
} }
} }
private static void WriteException(DiagnosticListener diagnosticListener, Exception exception, string message, string middlewareName, DownstreamContext context)
{
if(diagnosticListener != null)
{
diagnosticListener.Write(message, new { name = middlewareName, context = context, exception = exception });
}
}
public static IOcelotPipelineBuilder MapWhen(this IOcelotPipelineBuilder app, Predicate predicate, Action<IOcelotPipelineBuilder> configuration) public static IOcelotPipelineBuilder MapWhen(this IOcelotPipelineBuilder app, Predicate predicate, Action<IOcelotPipelineBuilder> configuration)
{ {
if (app == null) if (app == null)

View File

@ -12,28 +12,27 @@ namespace Ocelot.QueryStrings.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IAddQueriesToRequest _addQueriesToRequest; private readonly IAddQueriesToRequest _addQueriesToRequest;
private readonly IOcelotLogger _logger;
public QueryStringBuilderMiddleware(OcelotRequestDelegate next, public QueryStringBuilderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IAddQueriesToRequest addQueriesToRequest) IAddQueriesToRequest addQueriesToRequest)
: base(loggerFactory.CreateLogger<QueryStringBuilderMiddleware>())
{ {
_next = next; _next = next;
_addQueriesToRequest = addQueriesToRequest; _addQueriesToRequest = addQueriesToRequest;
_logger = loggerFactory.CreateLogger<QueryStringBuilderMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (context.DownstreamReRoute.ClaimsToQueries.Any()) if (context.DownstreamReRoute.ClaimsToQueries.Any())
{ {
_logger.LogDebug($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries"); Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(context.DownstreamReRoute.ClaimsToQueries, context.HttpContext.User.Claims, context.DownstreamRequest); var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(context.DownstreamReRoute.ClaimsToQueries, context.HttpContext.User.Claims, context.DownstreamRequest);
if (response.IsError) if (response.IsError)
{ {
_logger.LogDebug("there was an error setting queries on context, setting pipeline error"); Logger.LogWarning("there was an error setting queries on context, setting pipeline error");
SetPipelineError(context, response.Errors); SetPipelineError(context, response.Errors);
return; return;

View File

@ -40,9 +40,13 @@ namespace Ocelot.Raft
using(var reader = new StreamReader(HttpContext.Request.Body)) using(var reader = new StreamReader(HttpContext.Request.Body))
{ {
var json = await reader.ReadToEndAsync(); var json = await reader.ReadToEndAsync();
var appendEntries = JsonConvert.DeserializeObject<AppendEntries>(json, _jsonSerialiserSettings); var appendEntries = JsonConvert.DeserializeObject<AppendEntries>(json, _jsonSerialiserSettings);
_logger.LogDebug($"{_baseSchemeUrlAndPort}/appendentries called, my state is {_node.State.GetType().FullName}"); _logger.LogDebug($"{_baseSchemeUrlAndPort}/appendentries called, my state is {_node.State.GetType().FullName}");
var appendEntriesResponse = _node.Handle(appendEntries); var appendEntriesResponse = _node.Handle(appendEntries);
return new OkObjectResult(appendEntriesResponse); return new OkObjectResult(appendEntriesResponse);
} }
} }
@ -53,9 +57,13 @@ namespace Ocelot.Raft
using(var reader = new StreamReader(HttpContext.Request.Body)) using(var reader = new StreamReader(HttpContext.Request.Body))
{ {
var json = await reader.ReadToEndAsync(); var json = await reader.ReadToEndAsync();
var requestVote = JsonConvert.DeserializeObject<RequestVote>(json, _jsonSerialiserSettings); var requestVote = JsonConvert.DeserializeObject<RequestVote>(json, _jsonSerialiserSettings);
_logger.LogDebug($"{_baseSchemeUrlAndPort}/requestvote called, my state is {_node.State.GetType().FullName}"); _logger.LogDebug($"{_baseSchemeUrlAndPort}/requestvote called, my state is {_node.State.GetType().FullName}");
var requestVoteResponse = _node.Handle(requestVote); var requestVoteResponse = _node.Handle(requestVote);
return new OkObjectResult(requestVoteResponse); return new OkObjectResult(requestVoteResponse);
} }
} }
@ -68,10 +76,15 @@ namespace Ocelot.Raft
using(var reader = new StreamReader(HttpContext.Request.Body)) using(var reader = new StreamReader(HttpContext.Request.Body))
{ {
var json = await reader.ReadToEndAsync(); var json = await reader.ReadToEndAsync();
var command = JsonConvert.DeserializeObject<ICommand>(json, _jsonSerialiserSettings); var command = JsonConvert.DeserializeObject<ICommand>(json, _jsonSerialiserSettings);
_logger.LogDebug($"{_baseSchemeUrlAndPort}/command called, my state is {_node.State.GetType().FullName}"); _logger.LogDebug($"{_baseSchemeUrlAndPort}/command called, my state is {_node.State.GetType().FullName}");
var commandResponse = _node.Accept(command); var commandResponse = _node.Accept(command);
json = JsonConvert.SerializeObject(commandResponse, _jsonSerialiserSettings); json = JsonConvert.SerializeObject(commandResponse, _jsonSerialiserSettings);
return StatusCode(200, json); return StatusCode(200, json);
} }
} }

View File

@ -14,16 +14,15 @@ namespace Ocelot.RateLimit.Middleware
public class ClientRateLimitMiddleware : OcelotMiddleware public class ClientRateLimitMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IRateLimitCounterHandler _counterHandler; private readonly IRateLimitCounterHandler _counterHandler;
private readonly ClientRateLimitProcessor _processor; private readonly ClientRateLimitProcessor _processor;
public ClientRateLimitMiddleware(OcelotRequestDelegate next, public ClientRateLimitMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IRateLimitCounterHandler counterHandler) IRateLimitCounterHandler counterHandler)
:base(loggerFactory.CreateLogger<ClientRateLimitMiddleware>())
{ {
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<ClientRateLimitMiddleware>();
_counterHandler = counterHandler; _counterHandler = counterHandler;
_processor = new ClientRateLimitProcessor(counterHandler); _processor = new ClientRateLimitProcessor(counterHandler);
} }
@ -35,7 +34,7 @@ namespace Ocelot.RateLimit.Middleware
// check if rate limiting is enabled // check if rate limiting is enabled
if (!context.DownstreamReRoute.EnableEndpointEndpointRateLimiting) if (!context.DownstreamReRoute.EnableEndpointEndpointRateLimiting)
{ {
_logger.LogDebug($"EndpointRateLimiting is not enabled for {context.DownstreamReRoute.DownstreamPathTemplate}"); Logger.LogInformation($"EndpointRateLimiting is not enabled for {context.DownstreamReRoute.DownstreamPathTemplate.Value}");
await _next.Invoke(context); await _next.Invoke(context);
return; return;
} }
@ -46,7 +45,7 @@ namespace Ocelot.RateLimit.Middleware
// check white list // check white list
if (IsWhitelisted(identity, options)) if (IsWhitelisted(identity, options))
{ {
_logger.LogDebug($"{context.DownstreamReRoute.DownstreamPathTemplate} is white listed from rate limiting"); Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} is white listed from rate limiting");
await _next.Invoke(context); await _next.Invoke(context);
return; return;
} }
@ -112,7 +111,8 @@ namespace Ocelot.RateLimit.Middleware
public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule, DownstreamReRoute downstreamReRoute) public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule, DownstreamReRoute downstreamReRoute)
{ {
_logger.LogDebug($"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule { downstreamReRoute.UpstreamPathTemplate }, TraceIdentifier {httpContext.TraceIdentifier}."); Logger.LogInformation(
$"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule { downstreamReRoute.UpstreamPathTemplate.Value }, TraceIdentifier {httpContext.TraceIdentifier}.");
} }
public virtual Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitOptions option, string retryAfter) public virtual Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitOptions option, string retryAfter)

View File

@ -65,5 +65,10 @@ namespace Ocelot.Request.Middleware
return uriBuilder.Uri.AbsoluteUri; return uriBuilder.Uri.AbsoluteUri;
} }
public override string ToString()
{
return ToUri();
}
} }
} }

View File

@ -11,15 +11,14 @@ namespace Ocelot.Request.Middleware
public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly Mapper.IRequestMapper _requestMapper; private readonly Mapper.IRequestMapper _requestMapper;
public DownstreamRequestInitialiserMiddleware(OcelotRequestDelegate next, public DownstreamRequestInitialiserMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
Mapper.IRequestMapper requestMapper) Mapper.IRequestMapper requestMapper)
:base(loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>())
{ {
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>();
_requestMapper = requestMapper; _requestMapper = requestMapper;
} }

View File

@ -1,14 +1,11 @@
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Collections.Generic; using System.Collections.Generic;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;
namespace Ocelot.RequestId.Middleware namespace Ocelot.RequestId.Middleware
@ -16,16 +13,15 @@ namespace Ocelot.RequestId.Middleware
public class ReRouteRequestIdMiddleware : OcelotMiddleware public class ReRouteRequestIdMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IRequestScopedDataRepository _requestScopedDataRepository; private readonly IRequestScopedDataRepository _requestScopedDataRepository;
public ReRouteRequestIdMiddleware(OcelotRequestDelegate next, public ReRouteRequestIdMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository) IRequestScopedDataRepository requestScopedDataRepository)
: base(loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>())
{ {
_next = next; _next = next;
_requestScopedDataRepository = requestScopedDataRepository; _requestScopedDataRepository = requestScopedDataRepository;
_logger = loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
@ -39,25 +35,22 @@ namespace Ocelot.RequestId.Middleware
// if get request ID is set on upstream request then retrieve it // if get request ID is set on upstream request then retrieve it
var key = context.DownstreamReRoute.RequestIdKey ?? DefaultRequestIdKey.Value; var key = context.DownstreamReRoute.RequestIdKey ?? DefaultRequestIdKey.Value;
StringValues upstreamRequestIds; if (context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
if (context.HttpContext.Request.Headers.TryGetValue(key, out upstreamRequestIds))
{ {
//set the traceidentifier
context.HttpContext.TraceIdentifier = upstreamRequestIds.First(); context.HttpContext.TraceIdentifier = upstreamRequestIds.First();
//todo fix looking in both places
//check if we have previous id in scoped repo //check if we have previous id in scoped repo
var previousRequestId = _requestScopedDataRepository.Get<string>("RequestId"); var previousRequestId = _requestScopedDataRepository.Get<string>("RequestId");
if (!previousRequestId.IsError && !string.IsNullOrEmpty(previousRequestId.Data)) if (!previousRequestId.IsError && !string.IsNullOrEmpty(previousRequestId.Data) && previousRequestId.Data != context.HttpContext.TraceIdentifier)
{ {
//we have a previous request id lets store it and update request id //we have a previous request id lets store it and update request id
_requestScopedDataRepository.Add<string>("PreviousRequestId", previousRequestId.Data); _requestScopedDataRepository.Add("PreviousRequestId", previousRequestId.Data);
_requestScopedDataRepository.Update<string>("RequestId", context.HttpContext.TraceIdentifier); _requestScopedDataRepository.Update("RequestId", context.HttpContext.TraceIdentifier);
} }
else else
{ {
//else just add request id //else just add request id
_requestScopedDataRepository.Add<string>("RequestId", context.HttpContext.TraceIdentifier); _requestScopedDataRepository.Add("RequestId", context.HttpContext.TraceIdentifier);
} }
} }

View File

@ -12,15 +12,14 @@ namespace Ocelot.Requester.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IHttpRequester _requester; private readonly IHttpRequester _requester;
private readonly IOcelotLogger _logger;
public HttpRequesterMiddleware(OcelotRequestDelegate next, public HttpRequesterMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IHttpRequester requester) IHttpRequester requester)
: base(loggerFactory.CreateLogger<HttpRequesterMiddleware>())
{ {
_next = next; _next = next;
_requester = requester; _requester = requester;
_logger = loggerFactory.CreateLogger<HttpRequesterMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
@ -29,13 +28,13 @@ namespace Ocelot.Requester.Middleware
if (response.IsError) if (response.IsError)
{ {
_logger.LogDebug("IHttpRequester returned an error, setting pipeline error"); Logger.LogDebug("IHttpRequester returned an error, setting pipeline error");
SetPipelineError(context, response.Errors); SetPipelineError(context, response.Errors);
return; return;
} }
_logger.LogDebug("setting http response message"); Logger.LogDebug("setting http response message");
context.DownstreamResponse = response.Data; context.DownstreamResponse = response.Data;
} }

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -13,7 +12,7 @@ namespace Ocelot.Requester
{ {
private readonly IServiceTracer _tracer; private readonly IServiceTracer _tracer;
private readonly IRequestScopedDataRepository _repo; private readonly IRequestScopedDataRepository _repo;
private const string prefix_spanId = "ot-spanId"; private const string PrefixSpanId = "ot-spanId";
public OcelotHttpTracingHandler( public OcelotHttpTracingHandler(
IServiceTracer tracer, IServiceTracer tracer,
@ -37,11 +36,10 @@ namespace Ocelot.Requester
HttpRequestMessage request, HttpRequestMessage request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
IEnumerable<string> traceIdVals = null; if (request.Headers.Contains(PrefixSpanId))
if (request.Headers.TryGetValues(prefix_spanId, out traceIdVals))
{ {
request.Headers.Remove(prefix_spanId); request.Headers.Remove(PrefixSpanId);
request.Headers.TryAddWithoutValidation(prefix_spanId, span.SpanContext.SpanId); request.Headers.TryAddWithoutValidation(PrefixSpanId, span.SpanContext.SpanId);
} }
_repo.Add("TraceId", span.SpanContext.TraceId); _repo.Add("TraceId", span.SpanContext.TraceId);

View File

@ -6,6 +6,7 @@ using Ocelot.Middleware;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.Extensions;
namespace Ocelot.Responder.Middleware namespace Ocelot.Responder.Middleware
{ {
@ -17,18 +18,17 @@ namespace Ocelot.Responder.Middleware
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IHttpResponder _responder; private readonly IHttpResponder _responder;
private readonly IErrorsToHttpStatusCodeMapper _codeMapper; private readonly IErrorsToHttpStatusCodeMapper _codeMapper;
private readonly IOcelotLogger _logger;
public ResponderMiddleware(OcelotRequestDelegate next, public ResponderMiddleware(OcelotRequestDelegate next,
IHttpResponder responder, IHttpResponder responder,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IErrorsToHttpStatusCodeMapper codeMapper IErrorsToHttpStatusCodeMapper codeMapper
) )
:base(loggerFactory.CreateLogger<ResponderMiddleware>())
{ {
_next = next; _next = next;
_responder = responder; _responder = responder;
_codeMapper = codeMapper; _codeMapper = codeMapper;
_logger = loggerFactory.CreateLogger<ResponderMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
@ -37,19 +37,13 @@ namespace Ocelot.Responder.Middleware
if (context.IsError) if (context.IsError)
{ {
var errors = context.Errors; Logger.LogWarning($"{context.Errors.ToErrorString()} errors found in {MiddlewareName}. Setting error response for request path:{context.HttpContext.Request.Path}, request method: {context.HttpContext.Request.Method}");
_logger.LogError($"{errors.Count} pipeline errors found in {MiddlewareName}. Setting error response status code");
foreach(var error in errors) SetErrorResponse(context.HttpContext, context.Errors);
{
_logger.LogError(error.Message);
}
SetErrorResponse(context.HttpContext, errors);
} }
else else
{ {
_logger.LogDebug("no pipeline errors, setting and returning completed response"); Logger.LogDebug("no pipeline errors, setting and returning completed response");
await _responder.SetResponseOnHttpContext(context.HttpContext, context.DownstreamResponse); await _responder.SetResponseOnHttpContext(context.HttpContext, context.DownstreamResponse);
} }
} }

View File

@ -5,11 +5,13 @@ namespace Ocelot.Responses
{ {
public class ErrorResponse : Response public class ErrorResponse : Response
{ {
public ErrorResponse(Error error) : base(new List<Error>{error}) public ErrorResponse(Error error)
: base(new List<Error>{error})
{ {
} }
public ErrorResponse(List<Error> errors) : base(errors) public ErrorResponse(List<Error> errors)
: base(errors)
{ {
} }
} }

View File

@ -15,14 +15,8 @@ namespace Ocelot.Responses
Errors = errors ?? new List<Error>(); Errors = errors ?? new List<Error>();
} }
public List<Error> Errors { get; private set; } public List<Error> Errors { get; }
public bool IsError public bool IsError => Errors.Count > 0;
{
get
{
return Errors.Count > 0;
}
}
} }
} }

View File

@ -47,7 +47,7 @@ namespace Ocelot.ServiceDiscovery.Providers
} }
else else
{ {
_logger.LogError($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"); _logger.LogWarning($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
} }
} }

View File

@ -11,13 +11,12 @@ namespace Ocelot.WebSockets.Middleware
public class WebSocketsProxyMiddleware : OcelotMiddleware public class WebSocketsProxyMiddleware : OcelotMiddleware
{ {
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
private IOcelotLogger _logger;
public WebSocketsProxyMiddleware(OcelotRequestDelegate next, public WebSocketsProxyMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory) IOcelotLoggerFactory loggerFactory)
:base(loggerFactory.CreateLogger<WebSocketsProxyMiddleware>())
{ {
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<WebSocketsProxyMiddleware>();
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)

View File

@ -37,11 +37,11 @@ namespace Ocelot.ManualTest
{ {
x.WithDictionaryHandle(); x.WithDictionaryHandle();
}) })
.AddOpenTracing(option => /* .AddOpenTracing(option =>
{ {
option.CollectorUrl = "http://localhost:9618"; option.CollectorUrl = "http://localhost:9618";
option.Service = "Ocelot.ManualTest"; option.Service = "Ocelot.ManualTest";
}) })*/
.AddAdministration("/administration", "secret"); .AddAdministration("/administration", "secret");
}) })
.ConfigureLogging((hostingContext, logging) => .ConfigureLogging((hostingContext, logging) =>

View File

@ -2,7 +2,7 @@
"Logging": { "Logging": {
"IncludeScopes": false, "IncludeScopes": false,
"LogLevel": { "LogLevel": {
"Default": "Error", "Default": "Trace",
"System": "Error", "System": "Error",
"Microsoft": "Error" "Microsoft": "Error"
} }

View File

@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Configuration
private void ThenTheLoggerIsCalledCorrectly() private void ThenTheLoggerIsCalledCorrectly()
{ {
_logger _logger
.Verify(x => x.LogDebug(It.IsAny<string>(), It.IsAny<string>()), Times.Once); .Verify(x => x.LogDebug(It.IsAny<string>()), Times.Once);
} }
private void ThenClaimsToThingsAreReturned() private void ThenClaimsToThingsAreReturned()

View File

@ -124,7 +124,7 @@ namespace Ocelot.UnitTests.Configuration
private void ThenTheLoggerIsCalledCorrectly(string message) private void ThenTheLoggerIsCalledCorrectly(string message)
{ {
_logger.Verify(x => x.LogError(message), Times.Once); _logger.Verify(x => x.LogWarning(message), Times.Once);
} }
[Fact] [Fact]

View File

@ -1,5 +1,3 @@
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Errors namespace Ocelot.UnitTests.Errors
{ {
using System; using System;
@ -15,18 +13,18 @@ namespace Ocelot.UnitTests.Errors
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware;
public class ExceptionHandlerMiddlewareTests public class ExceptionHandlerMiddlewareTests
{ {
bool _shouldThrowAnException = false; bool _shouldThrowAnException;
private Mock<IOcelotConfigurationProvider> _provider; private readonly Mock<IOcelotConfigurationProvider> _provider;
private Mock<IRequestScopedDataRepository> _repo; private readonly Mock<IRequestScopedDataRepository> _repo;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private ExceptionHandlerMiddleware _middleware; private readonly ExceptionHandlerMiddleware _middleware;
private DownstreamContext _downstreamContext; private readonly DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
public ExceptionHandlerMiddlewareTests() public ExceptionHandlerMiddlewareTests()
@ -59,7 +57,7 @@ namespace Ocelot.UnitTests.Errors
.And(_ => GivenTheConfigurationIs(config)) .And(_ => GivenTheConfigurationIs(config))
.When(_ => WhenICallTheMiddleware()) .When(_ => WhenICallTheMiddleware())
.Then(_ => ThenTheResponseIsOk()) .Then(_ => ThenTheResponseIsOk())
.And(_ => TheRequestIdIsNotSet()) .And(_ => TheAspDotnetRequestIdIsSet())
.BDDfy(); .BDDfy();
} }
@ -89,7 +87,7 @@ namespace Ocelot.UnitTests.Errors
} }
[Fact] [Fact]
public void ShouldNotSetRequestId() public void ShouldSetAspDotNetRequestId()
{ {
var config = new OcelotConfiguration(null, null, null, null); var config = new OcelotConfiguration(null, null, null, null);
@ -97,7 +95,7 @@ namespace Ocelot.UnitTests.Errors
.And(_ => GivenTheConfigurationIs(config)) .And(_ => GivenTheConfigurationIs(config))
.When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234")) .When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
.Then(_ => ThenTheResponseIsOk()) .Then(_ => ThenTheResponseIsOk())
.And(_ => TheRequestIdIsNotSet()) .And(_ => TheAspDotnetRequestIdIsSet())
.BDDfy(); .BDDfy();
} }
@ -146,29 +144,19 @@ namespace Ocelot.UnitTests.Errors
private void GivenTheConfigReturnsError() private void GivenTheConfigReturnsError()
{ {
var config = new OcelotConfiguration(null, null, null, null); var response = new Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
var response = new Ocelot.Responses.ErrorResponse<IOcelotConfiguration>(new FakeError());
_provider _provider
.Setup(x => x.Get()).ReturnsAsync(response); .Setup(x => x.Get()).ReturnsAsync(response);
} }
public class FakeError : Error
{
public FakeError()
: base("meh", OcelotErrorCode.CannotAddDataError)
{
}
}
private void TheRequestIdIsSet(string key, string value) private void TheRequestIdIsSet(string key, string value)
{ {
_repo.Verify(x => x.Add<string>(key, value), Times.Once); _repo.Verify(x => x.Add(key, value), Times.Once);
} }
private void GivenTheConfigurationIs(IOcelotConfiguration config) private void GivenTheConfigurationIs(IOcelotConfiguration config)
{ {
var response = new Ocelot.Responses.OkResponse<IOcelotConfiguration>(config); var response = new Responses.OkResponse<IOcelotConfiguration>(config);
_provider _provider
.Setup(x => x.Get()).ReturnsAsync(response); .Setup(x => x.Get()).ReturnsAsync(response);
} }
@ -193,9 +181,17 @@ namespace Ocelot.UnitTests.Errors
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500); _downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
} }
private void TheRequestIdIsNotSet() private void TheAspDotnetRequestIdIsSet()
{ {
_repo.Verify(x => x.Add<string>(It.IsAny<string>(), It.IsAny<string>()), Times.Never); _repo.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
class FakeError : Error
{
internal FakeError()
: base("meh", OcelotErrorCode.CannotAddDataError)
{
}
} }
} }
} }

View File

@ -106,7 +106,7 @@ namespace Ocelot.UnitTests.Headers
private void ThenTheErrorIsLogged() private void ThenTheErrorIsLogged()
{ {
_logger.Verify(x => x.LogError("Unable to add header to response Trace-Id: {TraceId}"), Times.Once); _logger.Verify(x => x.LogWarning("Unable to add header to response Trace-Id: {TraceId}"), Times.Once);
} }
private void ThenTheHeaderIsNotAdded(string key) private void ThenTheHeaderIsNotAdded(string key)

View 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);
}
}
}

View 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));
}
}
}

View 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)
{
}
}
}

View File

@ -57,4 +57,8 @@
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="WebSockets\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,9 +1,6 @@
using Ocelot.Middleware; namespace Ocelot.UnitTests.RequestId
namespace Ocelot.UnitTests.RequestId
{ {
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -21,6 +18,7 @@ namespace Ocelot.UnitTests.RequestId
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;
using Ocelot.Middleware;
public class ReRouteRequestIdMiddlewareTests public class ReRouteRequestIdMiddlewareTests
{ {
@ -142,6 +140,30 @@ namespace Ocelot.UnitTests.RequestId
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_not_update_if_global_request_id_is_same_as_re_route_request_id()
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
var requestId = "alreadyset";
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => GivenTheRequestIdWasSetGlobally())
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheTraceIdIs(requestId))
.And(x => ThenTheRequestIdIsNotUpdated())
.BDDfy();
}
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()
{ {
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
@ -159,12 +181,17 @@ namespace Ocelot.UnitTests.RequestId
private void ThenTheRequestIdIsSaved() private void ThenTheRequestIdIsSaved()
{ {
_repo.Verify(x => x.Add<string>("RequestId", _value), Times.Once); _repo.Verify(x => x.Add("RequestId", _value), Times.Once);
} }
private void ThenTheRequestIdIsUpdated() private void ThenTheRequestIdIsUpdated()
{ {
_repo.Verify(x => x.Update<string>("RequestId", _value), Times.Once); _repo.Verify(x => x.Update("RequestId", _value), Times.Once);
}
private void ThenTheRequestIdIsNotUpdated()
{
_repo.Verify(x => x.Update("RequestId", _value), Times.Never);
} }
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
@ -182,15 +209,13 @@ namespace Ocelot.UnitTests.RequestId
private void ThenTheTraceIdIsAnything() private void ThenTheTraceIdIsAnything()
{ {
StringValues value; _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
_downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
value.First().ShouldNotBeNullOrEmpty(); value.First().ShouldNotBeNullOrEmpty();
} }
private void ThenTheTraceIdIs(string expected) private void ThenTheTraceIdIs(string expected)
{ {
StringValues value; _downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
_downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
value.First().ShouldBe(expected); value.First().ShouldBe(expected);
} }
} }

View File

@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.Responder
public void should_return_any_errors() public void should_return_any_errors()
{ {
this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage())) this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage()))
.And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError())) .And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError("/path", "GET")))
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenThereAreNoErrors()) .Then(x => x.ThenThereAreNoErrors())
.BDDfy(); .BDDfy();

View File

@ -142,12 +142,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress() private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
{ {
_logger.Verify( _logger.Verify(
x => x.LogError( x => x.LogWarning(
"Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"), "Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once); Times.Once);
_logger.Verify( _logger.Verify(
x => x.LogError( x => x.LogWarning(
"Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"), "Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once); Times.Once);
} }
@ -155,12 +155,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts() private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
{ {
_logger.Verify( _logger.Verify(
x => x.LogError( x => x.LogWarning(
"Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"), "Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once); Times.Once);
_logger.Verify( _logger.Verify(
x => x.LogError( x => x.LogWarning(
"Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"), "Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once); Times.Once);
} }