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