Merge branch 'release/5.5.0'

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,4 +9,4 @@ namespace Ocelot.Configuration
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
string RequestId {get;}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

@ -16,4 +16,4 @@ namespace Ocelot.Errors
return Message;
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData;
namespace Ocelot.Logging
{
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData;
namespace Ocelot.Logging
{
public class AspDotNetLoggerFactory : IOcelotLoggerFactory
{
private readonly ILoggerFactory _loggerFactory;
@ -17,7 +17,7 @@ namespace Ocelot.Logging
public IOcelotLogger CreateLogger<T>()
{
var logger = _loggerFactory.CreateLogger<T>();
return new AspDotNetLogger(logger, _scopedDataRepository, typeof(T).Name);
return new AspDotNetLogger(logger, _scopedDataRepository);
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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