From 637d93dc4bb21162d05767bab1366105524f8ff3 Mon Sep 17 00:00:00 2001 From: Marc Denman Date: Mon, 17 Apr 2017 11:23:34 +0100 Subject: [PATCH 1/5] Use DiagnosticListner for middleware logging Instead of each middleware having to log that it has started and ended, the DianosticListner package allows for capturing of these events in a lightwieght manner. This commit implements this and removes unncessary logging from most middleware. --- .../Middleware/AuthenticationMiddleware.cs | 16 +------ .../Middleware/AuthorisationMiddleware.cs | 21 +++------ .../Cache/Middleware/OutputCacheMiddleware.cs | 2 - .../Middleware/ClaimsBuilderMiddleware.cs | 7 --- .../ServiceCollectionExtensions.cs | 5 +++ .../DownstreamRouteFinderMiddleware.cs | 9 ---- .../DownstreamUrlCreatorMiddleware.cs | 6 --- .../HttpRequestHeadersBuilderMiddleware.cs | 10 +---- .../Middleware/LoadBalancingMiddleware.cs | 20 ++++----- .../Logging/OcelotDiagnosticListener.cs | 27 +++++++++++ .../Middleware/OcelotMiddlewareExtensions.cs | 45 ++++++++++++++----- src/Ocelot/Ocelot.csproj | 2 + .../QueryStringBuilderMiddleware.cs | 8 +--- .../Middleware/ClientRateLimitMiddleware.cs | 25 +++-------- .../Middleware/RequestIdMiddleware.cs | 14 ++---- .../Middleware/ResponderMiddleware.cs | 6 +-- 16 files changed, 98 insertions(+), 125 deletions(-) create mode 100644 src/Ocelot/Logging/OcelotDiagnosticListener.cs diff --git a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs index a6eb9cc2..7a292ea0 100644 --- a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs +++ b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs @@ -34,8 +34,6 @@ namespace Ocelot.Authentication.Middleware public async Task Invoke(HttpContext context) { - _logger.TraceMiddlewareEntry(); - if (IsAuthenticatedRoute(DownstreamRoute.ReRoute)) { _logger.LogDebug($"{context.Request.Path} is an authenticated route. {MiddlwareName} checking if client is authenticated"); @@ -46,7 +44,6 @@ namespace Ocelot.Authentication.Middleware { _logger.LogError($"Error getting authentication handler for {context.Request.Path}. {authenticationHandler.Errors.ToErrorString()}"); SetPipelineError(authenticationHandler.Errors); - _logger.TraceMiddlewareCompleted(); return; } @@ -56,11 +53,7 @@ namespace Ocelot.Authentication.Middleware if (context.User.Identity.IsAuthenticated) { _logger.LogDebug($"Client has been authenticated for {context.Request.Path}"); - - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); + await _next.Invoke(context); } else { @@ -72,8 +65,6 @@ namespace Ocelot.Authentication.Middleware _logger.LogError($"Client has NOT been authenticated for {context.Request.Path} and pipeline error set. {error.ToErrorString()}"); SetPipelineError(error); - - _logger.TraceMiddlewareCompleted(); return; } } @@ -81,10 +72,7 @@ namespace Ocelot.Authentication.Middleware { _logger.LogTrace($"No authentication needed for {context.Request.Path}"); - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); + await _next.Invoke(context); } } diff --git a/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs b/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs index a86643a4..c52b7329 100644 --- a/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs +++ b/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs @@ -29,17 +29,15 @@ namespace Ocelot.Authorisation.Middleware public async Task Invoke(HttpContext context) { - _logger.LogDebug("started authorisation"); - if (DownstreamRoute.ReRoute.IsAuthorised) { - _logger.LogDebug("route is authorised"); + _logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} route requires user to be authorised"); var authorised = _authoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement); if (authorised.IsError) { - _logger.LogDebug("error authorising user"); + _logger.LogDebug($"Error whilst authorising {context.User.Identity.Name} for {context.User.Identity.Name}. Setting pipeline error"); SetPipelineError(authorised.Errors); return; @@ -47,30 +45,23 @@ namespace Ocelot.Authorisation.Middleware if (IsAuthorised(authorised)) { - _logger.LogDebug("user is authorised calling next middleware"); - + _logger.LogDebug($"{context.User.Identity.Name} has succesfully been authorised for {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}. Calling next middleware"); await _next.Invoke(context); - - _logger.LogDebug("succesfully called next middleware"); } else { - _logger.LogDebug("user is not authorised setting pipeline error"); + _logger.LogDebug($"{context.User.Identity.Name} is not authorised to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}. Setting pipeline error"); SetPipelineError(new List { - new UnauthorisedError( - $"{context.User.Identity.Name} unable to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}") + new UnauthorisedError($"{context.User.Identity.Name} is not authorised to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}") }); } } else { - _logger.LogDebug("AuthorisationMiddleware.Invoke route is not authorised calling next middleware"); - + _logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised"); await _next.Invoke(context); - - _logger.LogDebug("succesfully called next middleware"); } } diff --git a/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs b/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs index 948a7397..2c2aceaa 100644 --- a/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs +++ b/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs @@ -54,8 +54,6 @@ namespace Ocelot.Cache.Middleware await _next.Invoke(context); - _logger.LogDebug("succesfully called next middleware"); - if (PipelineError) { _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey); diff --git a/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs index 1b1745e2..9a2e4239 100644 --- a/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs +++ b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs @@ -26,8 +26,6 @@ namespace Ocelot.Claims.Middleware public async Task Invoke(HttpContext context) { - _logger.LogDebug("started claims middleware"); - if (DownstreamRoute.ReRoute.ClaimsToClaims.Any()) { _logger.LogDebug("this route has instructions to convert claims to other claims"); @@ -42,12 +40,7 @@ namespace Ocelot.Claims.Middleware return; } } - - _logger.LogDebug("calling next middleware"); - await _next.Invoke(context); - - _logger.LogDebug("succesfully called next middleware"); } } } diff --git a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs index e975dcb6..66af481e 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -166,6 +166,11 @@ namespace Ocelot.DependencyInjection services.TryAddSingleton(); services.TryAddScoped(); services.AddMemoryCache(); + + //Used to log the the start and ending of middleware + services.TryAddSingleton(); + services.AddMiddlewareAnalysis(); + return services; } } diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index c107a2f5..8fdd2a54 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -30,8 +30,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware public async Task Invoke(HttpContext context) { - _logger.TraceMiddlewareEntry(); - var upstreamUrlPath = context.Request.Path.ToString().SetLastCharacterAs('/'); _logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath); @@ -43,8 +41,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware _logger.LogError($"{MiddlwareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}"); SetPipelineError(downstreamRoute.Errors); - - _logger.TraceMiddlewareCompleted(); return; } @@ -52,12 +48,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware SetDownstreamRouteForThisRequest(downstreamRoute.Data); - _logger.TraceInvokeNext(); - await _next.Invoke(context); - - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); } } } \ No newline at end of file diff --git a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs index 631e278a..bd364b5e 100644 --- a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -29,8 +29,6 @@ namespace Ocelot.DownstreamUrlCreator.Middleware public async Task Invoke(HttpContext context) { - _logger.LogDebug("started calling downstream url creator middleware"); - var dsPath = _replacer .Replace(DownstreamRoute.ReRoute.DownstreamPathTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues); @@ -60,11 +58,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware SetDownstreamUrlForThisRequest(dsUrl.Data.Value); - _logger.LogDebug("calling next middleware"); - await _next.Invoke(context); - - _logger.LogDebug("succesfully called next middleware"); } } } \ No newline at end of file diff --git a/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs index a89d2ec2..8ad155b1 100644 --- a/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs +++ b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs @@ -26,17 +26,15 @@ namespace Ocelot.Headers.Middleware public async Task Invoke(HttpContext context) { - _logger.LogDebug("started calling headers builder middleware"); - if (DownstreamRoute.ReRoute.ClaimsToHeaders.Any()) { - _logger.LogDebug("this route has instructions to convert claims to headers"); + _logger.LogDebug($"{ DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers"); var response = _addHeadersToRequest.SetHeadersOnContext(DownstreamRoute.ReRoute.ClaimsToHeaders, context); if (response.IsError) { - _logger.LogDebug("there was an error setting headers on context, setting pipeline error"); + _logger.LogDebug("Error setting headers on context, setting pipeline error"); SetPipelineError(response.Errors); return; @@ -45,11 +43,7 @@ namespace Ocelot.Headers.Middleware _logger.LogDebug("headers have been set on context"); } - _logger.LogDebug("calling next middleware"); - await _next.Invoke(context); - - _logger.LogDebug("succesfully called next middleware"); } } } diff --git a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs index 8e26cbf2..e432b21f 100644 --- a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs +++ b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs @@ -28,41 +28,37 @@ namespace Ocelot.LoadBalancer.Middleware public async Task Invoke(HttpContext context) { - _logger.LogDebug("started calling load balancing middleware"); - var loadBalancer = _loadBalancerHouse.Get(DownstreamRoute.ReRoute.ReRouteKey); if(loadBalancer.IsError) { + _logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error"); SetPipelineError(loadBalancer.Errors); return; } var hostAndPort = await loadBalancer.Data.Lease(); if(hostAndPort.IsError) - { + { + _logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error"); SetPipelineError(hostAndPort.Errors); return; } SetHostAndPortForThisRequest(hostAndPort.Data); - _logger.LogDebug("calling next middleware"); - try { await _next.Invoke(context); - - loadBalancer.Data.Release(hostAndPort.Data); } catch (Exception) { - loadBalancer.Data.Release(hostAndPort.Data); - - _logger.LogDebug("error calling next middleware, exception will be thrown to global handler"); + _logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler"); throw; } - - _logger.LogDebug("succesfully called next middleware"); + finally + { + loadBalancer.Data.Release(hostAndPort.Data); + } } } } diff --git a/src/Ocelot/Logging/OcelotDiagnosticListener.cs b/src/Ocelot/Logging/OcelotDiagnosticListener.cs new file mode 100644 index 00000000..06933834 --- /dev/null +++ b/src/Ocelot/Logging/OcelotDiagnosticListener.cs @@ -0,0 +1,27 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DiagnosticAdapter; + +namespace Ocelot.Logging +{ + public class OcelotDiagnosticListener + { + [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareStarting")] + public virtual void OnMiddlewareStarting(HttpContext httpContext, string name) + { + Console.WriteLine($"MiddlewareStarting: {name}; {httpContext.Request.Path}"); + } + + [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")] + public virtual void OnMiddlewareException(Exception exception, string name) + { + Console.WriteLine($"MiddlewareException: {name}; {exception.Message}"); + } + + [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")] + public virtual void OnMiddlewareFinished(HttpContext httpContext, string name) + { + Console.WriteLine($"MiddlewareFinished: {name}; {httpContext.Response.StatusCode}"); + } + } +} diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index 457c2448..faf2f648 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; +using System.Diagnostics; using IdentityServer4.AccessTokenValidation; using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; using Ocelot.Authentication.Middleware; using Ocelot.Cache.Middleware; using Ocelot.Claims.Middleware; @@ -8,6 +10,7 @@ using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamUrlCreator.Middleware; using Ocelot.Errors.Middleware; using Ocelot.Headers.Middleware; +using Ocelot.Logging; using Ocelot.QueryStrings.Middleware; using Ocelot.Request.Middleware; using Ocelot.Requester.Middleware; @@ -49,10 +52,12 @@ namespace Ocelot.Middleware /// /// /// - public static async Task UseOcelot(this IApplicationBuilder builder, OcelotMiddlewareConfiguration middlewareConfiguration) - { + public static async Task UseOcelot(this IApplicationBuilder builder, OcelotMiddlewareConfiguration middlewareConfiguration) + { await CreateAdministrationArea(builder); + ConfigureDiagnosticListener(builder); + // This is registered to catch any global exceptions that are not handled builder.UseExceptionHandlerMiddleware(); @@ -135,10 +140,10 @@ namespace Ocelot.Middleware private static async Task CreateConfiguration(IApplicationBuilder builder) { - var fileConfig = (IOptions)builder.ApplicationServices.GetService(typeof(IOptions)); - - var configSetter = (IFileConfigurationSetter)builder.ApplicationServices.GetService(typeof(IFileConfigurationSetter)); - + var fileConfig = (IOptions)builder.ApplicationServices.GetService(typeof(IOptions)); + + var configSetter = (IFileConfigurationSetter)builder.ApplicationServices.GetService(typeof(IFileConfigurationSetter)); + var configProvider = (IOcelotConfigurationProvider)builder.ApplicationServices.GetService(typeof(IOcelotConfigurationProvider)); var ocelotConfiguration = await configProvider.Get(); @@ -155,7 +160,7 @@ namespace Ocelot.Middleware ocelotConfiguration = await configProvider.Get(); - if(ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError) + if (ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError) { throw new Exception("Unable to start Ocelot: ocelot configuration was not returned by provider."); } @@ -169,15 +174,15 @@ namespace Ocelot.Middleware var identityServerConfiguration = (IIdentityServerConfiguration)builder.ApplicationServices.GetService(typeof(IIdentityServerConfiguration)); - if(!string.IsNullOrEmpty(configuration.AdministrationPath) && identityServerConfiguration != null) + if (!string.IsNullOrEmpty(configuration.AdministrationPath) && identityServerConfiguration != null) { var urlFinder = (IBaseUrlFinder)builder.ApplicationServices.GetService(typeof(IBaseUrlFinder)); - var baseSchemeUrlAndPort = urlFinder.Find(); - + var baseSchemeUrlAndPort = urlFinder.Find(); + builder.Map(configuration.AdministrationPath, app => { - var identityServerUrl = $"{baseSchemeUrlAndPort}/{configuration.AdministrationPath.Remove(0,1)}"; + var identityServerUrl = $"{baseSchemeUrlAndPort}/{configuration.AdministrationPath.Remove(0, 1)}"; app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions { @@ -195,7 +200,23 @@ namespace Ocelot.Middleware }); } } - + + /// + /// Configure a DiagnosticListener to listen for diagnostic events when the middleware starts and ends + /// + /// + private static void ConfigureDiagnosticListener(IApplicationBuilder builder) + { + + var env = builder.ApplicationServices.GetService(); + if (!env.IsProduction()) + { + var listener = builder.ApplicationServices.GetService(); + var diagnosticListener = builder.ApplicationServices.GetService(); + diagnosticListener.SubscribeWithAdapter(listener); + } + } + private static void UseIfNotNull(this IApplicationBuilder builder, Func, Task> middleware) { if (middleware != null) diff --git a/src/Ocelot/Ocelot.csproj b/src/Ocelot/Ocelot.csproj index 8fdb917d..554570ad 100644 --- a/src/Ocelot/Ocelot.csproj +++ b/src/Ocelot/Ocelot.csproj @@ -21,10 +21,12 @@ + + diff --git a/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs index edeee51c..355692ec 100644 --- a/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs +++ b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs @@ -26,11 +26,9 @@ namespace Ocelot.QueryStrings.Middleware public async Task Invoke(HttpContext context) { - _logger.LogDebug("started calling query string builder middleware"); - if (DownstreamRoute.ReRoute.ClaimsToQueries.Any()) { - _logger.LogDebug("this route has instructions to convert claims to queries"); + _logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries"); var response = _addQueriesToRequest.SetQueriesOnContext(DownstreamRoute.ReRoute.ClaimsToQueries, context); @@ -43,11 +41,7 @@ namespace Ocelot.QueryStrings.Middleware } } - _logger.LogDebug("calling next middleware"); - await _next.Invoke(context); - - _logger.LogDebug("succesfully called next middleware"); } } } diff --git a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs index dffc6448..819bbf1d 100644 --- a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs +++ b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs @@ -31,18 +31,13 @@ namespace Ocelot.RateLimit.Middleware public async Task Invoke(HttpContext context) { - _logger.TraceMiddlewareEntry(); - var options = DownstreamRoute.ReRoute.RateLimitOptions; // check if rate limiting is enabled if (!DownstreamRoute.ReRoute.EnableEndpointEndpointRateLimiting) { _logger.LogDebug($"EndpointRateLimiting is not enabled for {DownstreamRoute.ReRoute.DownstreamPathTemplate}"); + await _next.Invoke(context); - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); return; } // compute identity from request @@ -52,11 +47,8 @@ namespace Ocelot.RateLimit.Middleware if (IsWhitelisted(identity, options)) { _logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate} is white listed from rate limiting"); + await _next.Invoke(context); - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); return; } @@ -77,21 +69,18 @@ namespace Ocelot.RateLimit.Middleware // break execution await ReturnQuotaExceededResponse(context, options, retryAfter); - _logger.TraceMiddlewareCompleted(); return; } } //set X-Rate-Limit headers for the longest period if (!options.DisableRateLimitHeaders) { - var headers = _processor.GetRateLimitHeaders( context,identity, options); + var headers = _processor.GetRateLimitHeaders(context, identity, options); context.Response.OnStarting(SetRateLimitHeaders, state: headers); } - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); + await _next.Invoke(context); + } public virtual ClientRequestIdentity SetIdentity(HttpContext httpContext, RateLimitOptions option) @@ -104,10 +93,10 @@ namespace Ocelot.RateLimit.Middleware return new ClientRequestIdentity( clientId, - httpContext.Request.Path.ToString().ToLowerInvariant(), + httpContext.Request.Path.ToString().ToLowerInvariant(), httpContext.Request.Method.ToLowerInvariant() ); - } + } public bool IsWhitelisted(ClientRequestIdentity requestIdentity, RateLimitOptions option) { diff --git a/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs b/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs index 1e1a955c..37ed6d0c 100644 --- a/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs +++ b/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs @@ -17,7 +17,7 @@ namespace Ocelot.RequestId.Middleware public RequestIdMiddleware(RequestDelegate next, IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository) - :base(requestScopedDataRepository) + : base(requestScopedDataRepository) { _next = next; _logger = loggerFactory.CreateLogger(); @@ -25,17 +25,11 @@ namespace Ocelot.RequestId.Middleware } public async Task Invoke(HttpContext context) - { - _logger.TraceMiddlewareEntry(); - + { SetOcelotRequestId(context); - _logger.LogDebug("set requestId"); - - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); - _logger.TraceMiddlewareCompleted(); + _logger.LogDebug("set requestId"); + await _next.Invoke(context); } private void SetOcelotRequestId(HttpContext context) diff --git a/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs index 7e843486..2b6f52f1 100644 --- a/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs +++ b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs @@ -34,10 +34,7 @@ namespace Ocelot.Responder.Middleware public async Task Invoke(HttpContext context) { - _logger.TraceMiddlewareEntry(); - _logger.TraceInvokeNext(); - await _next.Invoke(context); - _logger.TraceInvokeNextCompleted(); + await _next.Invoke(context); if (PipelineError) { @@ -51,7 +48,6 @@ namespace Ocelot.Responder.Middleware _logger.LogDebug("no pipeline errors, setting and returning completed response"); await _responder.SetResponseOnHttpContext(context, HttpResponseMessage); } - _logger.TraceMiddlewareCompleted(); } private void SetErrorResponse(HttpContext context, List errors) From 2d94884c6f6ac35e3bec13a0a729995fde983303 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Fri, 23 Jun 2017 11:25:23 +0100 Subject: [PATCH 2/5] trying to get cluster working --- .../IdentityServerConfigurationCreator.cs | 6 ++- .../Provider/IIdentityServerConfiguration.cs | 2 + .../Provider/IdentityServerConfiguration.cs | 6 ++- .../ServiceCollectionExtensions.cs | 15 +++++- .../Ocelot.AcceptanceTests.csproj | 2 +- .../AdministrationTests.cs | 48 +++++++++++++++++++ .../Ocelot.IntegrationTests.csproj | 2 +- 7 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs index 48819608..6ed3b6c0 100644 --- a/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs @@ -13,6 +13,8 @@ namespace Ocelot.Configuration.Creator var username = Environment.GetEnvironmentVariable("OCELOT_USERNAME"); var hash = Environment.GetEnvironmentVariable("OCELOT_HASH"); var salt = Environment.GetEnvironmentVariable("OCELOT_SALT"); + var credentialsSigningCertificateLocation = Environment.GetEnvironmentVariable("OCELOT_CERTIFICATE"); + var credentialsSigningCertificatePassword = Environment.GetEnvironmentVariable("OCELOT_CERTIFICATE_PASSWORD"); return new IdentityServerConfiguration( "admin", @@ -28,7 +30,9 @@ namespace Ocelot.Configuration.Creator new List { new User("admin", username, hash, salt) - } + }, + credentialsSigningCertificateLocation, + credentialsSigningCertificatePassword ); } } diff --git a/src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs b/src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs index bb66265f..0a388abb 100644 --- a/src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs +++ b/src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs @@ -17,5 +17,7 @@ namespace Ocelot.Configuration.Provider AccessTokenType AccessTokenType {get;} bool RequireClientSecret {get;} List Users {get;} + string CredentialsSigningCertificateLocation { get; } + string CredentialsSigningCertificatePassword { get; } } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs b/src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs index f0f6897d..881d6f5a 100644 --- a/src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs +++ b/src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs @@ -17,7 +17,7 @@ namespace Ocelot.Configuration.Provider IEnumerable grantType, AccessTokenType accessTokenType, bool requireClientSecret, - List users) + List users, string credentialsSigningCertificateLocation, string credentialsSigningCertificatePassword) { ApiName = apiName; RequireHttps = requireHttps; @@ -30,6 +30,8 @@ namespace Ocelot.Configuration.Provider AccessTokenType = accessTokenType; RequireClientSecret = requireClientSecret; Users = users; + CredentialsSigningCertificateLocation = credentialsSigningCertificateLocation; + CredentialsSigningCertificatePassword = credentialsSigningCertificatePassword; } public string ApiName { get; private set; } @@ -43,5 +45,7 @@ namespace Ocelot.Configuration.Provider public AccessTokenType AccessTokenType {get;private set;} public bool RequireClientSecret {get;private set;} public List Users {get;private set;} + public string CredentialsSigningCertificateLocation { get; private set; } + public string CredentialsSigningCertificatePassword { get; private set; } } } \ No newline at end of file diff --git a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs index d52341fe..6b33f5c7 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -41,6 +41,8 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Reflection; +using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Tokens; using Ocelot.Configuration; using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider; @@ -87,8 +89,7 @@ namespace Ocelot.DependencyInjection { services.TryAddSingleton(identityServerConfiguration); services.TryAddSingleton(); - services.AddIdentityServer() - .AddTemporarySigningCredential() + var identityServerBuilder = services.AddIdentityServer() .AddInMemoryApiResources(new List { new ApiResource @@ -120,6 +121,16 @@ namespace Ocelot.DependencyInjection RequireClientSecret = identityServerConfiguration.RequireClientSecret } }).AddResourceOwnerValidator(); + + if (string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificateLocation) || string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificatePassword)) + { + identityServerBuilder.AddTemporarySigningCredential(); + } + else + { + var cert = new X509Certificate2(identityServerConfiguration.CredentialsSigningCertificateLocation, identityServerConfiguration.CredentialsSigningCertificatePassword); + identityServerBuilder.AddSigningCredential(cert); + } } var assembly = typeof(FileConfigurationController).GetTypeInfo().Assembly; diff --git a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj index 0faafe84..94e30391 100644 --- a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj +++ b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj @@ -15,7 +15,7 @@ - + PreserveNewest diff --git a/test/Ocelot.IntegrationTests/AdministrationTests.cs b/test/Ocelot.IntegrationTests/AdministrationTests.cs index 2fa2c05c..3f7ea18a 100644 --- a/test/Ocelot.IntegrationTests/AdministrationTests.cs +++ b/test/Ocelot.IntegrationTests/AdministrationTests.cs @@ -19,15 +19,19 @@ namespace Ocelot.IntegrationTests public class AdministrationTests : IDisposable { private readonly HttpClient _httpClient; + private readonly HttpClient _httpClientTwo; private HttpResponseMessage _response; private IWebHost _builder; private IWebHostBuilder _webHostBuilder; private readonly string _ocelotBaseUrl; private BearerToken _token; + private IWebHostBuilder _webHostBuilderTwo; + private IWebHost _builderTwo; public AdministrationTests() { _httpClient = new HttpClient(); + _httpClientTwo = new HttpClient(); _ocelotBaseUrl = "http://localhost:5000"; _httpClient.BaseAddress = new Uri(_ocelotBaseUrl); } @@ -70,6 +74,27 @@ namespace Ocelot.IntegrationTests .BDDfy(); } + [Fact] + public void should_be_able_to_use_token_from_ocelot_a_on_ocelot_b() + { + var configuration = new FileConfiguration + { + GlobalConfiguration = new FileGlobalConfiguration + { + AdministrationPath = "/administration" + } + }; + + this.Given(x => GivenThereIsAConfiguration(configuration)) + .And(x => GivenOcelotIsRunning()) + .And(x => GivenIHaveAnOcelotToken("/administration")) + .And(x => GivenIHaveAddedATokenToMyRequest()) + .And(x => GivenAnotherOcelotIsRunning("http://localhost:5007")) + .When(x => WhenIGetUrlOnTheSecondOcelot("/administration/configuration")) + .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .BDDfy(); + } + [Fact] public void should_return_file_configuration() { @@ -193,6 +218,29 @@ namespace Ocelot.IntegrationTests .BDDfy(); } + private void GivenAnotherOcelotIsRunning(string baseUrl) + { + _httpClientTwo.BaseAddress = new Uri(baseUrl); + + _webHostBuilderTwo = new WebHostBuilder() + .UseUrls(baseUrl) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureServices(x => { + x.AddSingleton(_webHostBuilder); + }) + .UseStartup(); + + _builderTwo = _webHostBuilderTwo.Build(); + + _builderTwo.Start(); + } + + private void WhenIGetUrlOnTheSecondOcelot(string url) + { + _response = _httpClientTwo.GetAsync(url).Result; + } + private void WhenIPostOnTheApiGateway(string url, FileConfiguration updatedConfiguration) { var json = JsonConvert.SerializeObject(updatedConfiguration); diff --git a/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj b/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj index db4b23d2..59513b38 100644 --- a/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj +++ b/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj @@ -15,7 +15,7 @@ - + PreserveNewest From 6cdf4e67df417bc514da9b445f9053e662f7b525 Mon Sep 17 00:00:00 2001 From: Tom Gardham-Pallister Date: Fri, 23 Jun 2017 15:17:40 +0100 Subject: [PATCH 3/5] can now use tokens from ocelot a on ocelot b when using admin area --- .gitignore | 1 + .../ServiceCollectionExtensions.cs | 5 ++++- .../Middleware/OcelotMiddlewareExtensions.cs | 1 - .../Ocelot.AcceptanceTests.csproj | 2 +- test/Ocelot.AcceptanceTests/appsettings.json | 10 ++++++++++ .../AdministrationTests.cs | 13 +++++++++++-- test/Ocelot.IntegrationTests/appsettings.json | 4 ++-- test/Ocelot.IntegrationTests/idsrv3test.pfx | Bin 0 -> 3395 bytes 8 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 test/Ocelot.AcceptanceTests/appsettings.json create mode 100644 test/Ocelot.IntegrationTests/idsrv3test.pfx diff --git a/.gitignore b/.gitignore index a2902800..f5dfbc4d 100644 --- a/.gitignore +++ b/.gitignore @@ -183,6 +183,7 @@ ClientBin/ *.dbmdl *.dbproj.schemaview *.pfx +!idsrv3test.pfx *.publishsettings node_modules/ orleans.codegen.cs diff --git a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs index 6b33f5c7..ae0e35de 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -89,7 +89,10 @@ namespace Ocelot.DependencyInjection { services.TryAddSingleton(identityServerConfiguration); services.TryAddSingleton(); - var identityServerBuilder = services.AddIdentityServer() + var identityServerBuilder = services + .AddIdentityServer(options => { + options.IssuerUri = "Ocelot"; + }) .AddInMemoryApiResources(new List { new ApiResource diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index 3f98f959..d2e91c6d 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -181,7 +181,6 @@ namespace Ocelot.Middleware builder.Map(configuration.AdministrationPath, app => { var identityServerUrl = $"{baseSchemeUrlAndPort}/{configuration.AdministrationPath.Remove(0,1)}"; - app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions { Authority = identityServerUrl, diff --git a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj index 94e30391..08bbf527 100644 --- a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj +++ b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj @@ -15,7 +15,7 @@ - + PreserveNewest diff --git a/test/Ocelot.AcceptanceTests/appsettings.json b/test/Ocelot.AcceptanceTests/appsettings.json new file mode 100644 index 00000000..df0788de --- /dev/null +++ b/test/Ocelot.AcceptanceTests/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Error", + "System": "Error", + "Microsoft": "Error" + } + } +} diff --git a/test/Ocelot.IntegrationTests/AdministrationTests.cs b/test/Ocelot.IntegrationTests/AdministrationTests.cs index 3f7ea18a..b03d587e 100644 --- a/test/Ocelot.IntegrationTests/AdministrationTests.cs +++ b/test/Ocelot.IntegrationTests/AdministrationTests.cs @@ -86,9 +86,9 @@ namespace Ocelot.IntegrationTests }; this.Given(x => GivenThereIsAConfiguration(configuration)) + .And(x => GivenIdentityServerSigningEnvironmentalVariablesAreSet()) .And(x => GivenOcelotIsRunning()) .And(x => GivenIHaveAnOcelotToken("/administration")) - .And(x => GivenIHaveAddedATokenToMyRequest()) .And(x => GivenAnotherOcelotIsRunning("http://localhost:5007")) .When(x => WhenIGetUrlOnTheSecondOcelot("/administration/configuration")) .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) @@ -227,7 +227,7 @@ namespace Ocelot.IntegrationTests .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureServices(x => { - x.AddSingleton(_webHostBuilder); + x.AddSingleton(_webHostBuilderTwo); }) .UseStartup(); @@ -236,8 +236,15 @@ namespace Ocelot.IntegrationTests _builderTwo.Start(); } + private void GivenIdentityServerSigningEnvironmentalVariablesAreSet() + { + Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE", "idsrv3test.pfx"); + Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE_PASSWORD", "idsrv3test"); + } + private void WhenIGetUrlOnTheSecondOcelot(string url) { + _httpClientTwo.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken); _response = _httpClientTwo.GetAsync(url).Result; } @@ -353,6 +360,8 @@ namespace Ocelot.IntegrationTests public void Dispose() { + Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE", ""); + Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE_PASSWORD", ""); _builder?.Dispose(); _httpClient?.Dispose(); } diff --git a/test/Ocelot.IntegrationTests/appsettings.json b/test/Ocelot.IntegrationTests/appsettings.json index 503cc778..df0788de 100644 --- a/test/Ocelot.IntegrationTests/appsettings.json +++ b/test/Ocelot.IntegrationTests/appsettings.json @@ -3,8 +3,8 @@ "IncludeScopes": true, "LogLevel": { "Default": "Error", - "System": "Information", - "Microsoft": "Information" + "System": "Error", + "Microsoft": "Error" } } } diff --git a/test/Ocelot.IntegrationTests/idsrv3test.pfx b/test/Ocelot.IntegrationTests/idsrv3test.pfx new file mode 100644 index 0000000000000000000000000000000000000000..0247dea03f0cc23694291f21310f3ae88880e2bb GIT binary patch literal 3395 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 V%$88{h~I%@Xjg7x^oQR@_8&Ry9S;Bi literal 0 HcmV?d00001 From e96d66139f58ea94352b1d2b85d9b0e5bd4025b1 Mon Sep 17 00:00:00 2001 From: Tom Gardham-Pallister Date: Sat, 24 Jun 2017 13:04:25 +0100 Subject: [PATCH 4/5] boost test coverage --- .../Creator/AuthenticationHandlerCreator.cs | 1 + ...IdentityServerConfigurationCreatorTests.cs | 16 +++ .../Errors/ExceptionHandlerMiddlewareTests.cs | 125 ++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 test/Ocelot.UnitTests/Configuration/IdentityServerConfigurationCreatorTests.cs create mode 100644 test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs diff --git a/src/Ocelot/Authentication/Handler/Creator/AuthenticationHandlerCreator.cs b/src/Ocelot/Authentication/Handler/Creator/AuthenticationHandlerCreator.cs index 96713fb0..1fcc50fb 100644 --- a/src/Ocelot/Authentication/Handler/Creator/AuthenticationHandlerCreator.cs +++ b/src/Ocelot/Authentication/Handler/Creator/AuthenticationHandlerCreator.cs @@ -1,3 +1,4 @@ +using System; using IdentityServer4.AccessTokenValidation; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; diff --git a/test/Ocelot.UnitTests/Configuration/IdentityServerConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/IdentityServerConfigurationCreatorTests.cs new file mode 100644 index 00000000..8d100e10 --- /dev/null +++ b/test/Ocelot.UnitTests/Configuration/IdentityServerConfigurationCreatorTests.cs @@ -0,0 +1,16 @@ +using Ocelot.Configuration.Creator; +using Shouldly; +using Xunit; + +namespace Ocelot.UnitTests.Configuration +{ + public class IdentityServerConfigurationCreatorTests + { + [Fact] + public void happy_path_only_exists_for_test_coverage_even_uncle_bob_probably_wouldnt_test_this() + { + var result = IdentityServerConfigurationCreator.GetIdentityServerConfiguration(); + result.ApiName.ShouldBe("admin"); + } + } +} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs new file mode 100644 index 00000000..41beffdc --- /dev/null +++ b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs @@ -0,0 +1,125 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Ocelot.DownstreamRouteFinder; +using Ocelot.DownstreamUrlCreator; +using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; +using Ocelot.Errors.Middleware; +using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; +using Ocelot.Responses; +using Ocelot.Values; +using Shouldly; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.Errors +{ + public class ExceptionHandlerMiddlewareTests + { + private readonly Mock _scopedRepository; + private readonly string _url; + private TestServer _server; + private HttpClient _client; + private HttpResponseMessage _result; + + public ExceptionHandlerMiddlewareTests() + { + _url = "http://localhost:52879"; + _scopedRepository = new Mock(); + } + + [Fact] + public void should_call_next_middleware() + { + this.Given(_ => GivenASuccessfulRequest()) + .When(_ => WhenIMakeTheRequest()) + .Then(_ => ThenTheResponseIsOk()) + .BDDfy(); + } + + [Fact] + public void should_call_return_error() + { + this.Given(_ => GivenAnError()) + .When(_ => WhenIMakeTheRequest()) + .Then(_ => ThenTheResponseIsError()) + .BDDfy(); + } + + private void ThenTheResponseIsOk() + { + _result.StatusCode.ShouldBe(HttpStatusCode.OK); + } + + private void ThenTheResponseIsError() + { + _result.StatusCode.ShouldBe(HttpStatusCode.InternalServerError); + } + + private void WhenIMakeTheRequest() + { + _result = _client.GetAsync("/").Result; + } + + private void GivenASuccessfulRequest() + { + var builder = new WebHostBuilder() + .ConfigureServices(x => + { + x.AddSingleton(); + x.AddLogging(); + x.AddSingleton(_scopedRepository.Object); + }) + .UseUrls(_url) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseUrls(_url) + .Configure(app => + { + app.UseExceptionHandlerMiddleware(); + app.Run(async context => + { + context.Response.StatusCode = 200; + }); + }); + + _server = new TestServer(builder); + _client = _server.CreateClient(); + } + + private void GivenAnError() + { + var builder = new WebHostBuilder() + .ConfigureServices(x => + { + x.AddSingleton(); + x.AddLogging(); + x.AddSingleton(_scopedRepository.Object); + }) + .UseUrls(_url) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseUrls(_url) + .Configure(app => + { + app.UseExceptionHandlerMiddleware(); + app.Use(async (context, next) => + { + throw new Exception("BOOM"); + }); + }); + + _server = new TestServer(builder); + _client = _server.CreateClient(); + } + } +} \ No newline at end of file From 26e7621798ed81d1f51abfee96879066b2f5742a Mon Sep 17 00:00:00 2001 From: TomPallister Date: Sun, 25 Jun 2017 22:07:19 +0100 Subject: [PATCH 5/5] fixed stupid double request bug from bad merge --- src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs | 4 ---- test/Ocelot.ManualTest/appsettings.json | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs index 2997504a..e8dbaeef 100644 --- a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs +++ b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs @@ -36,8 +36,6 @@ namespace Ocelot.RateLimit.Middleware if (!DownstreamRoute.ReRoute.EnableEndpointEndpointRateLimiting) { _logger.LogDebug($"EndpointRateLimiting is not enabled for {DownstreamRoute.ReRoute.DownstreamPathTemplate}"); - await _next.Invoke(context); - await _next.Invoke(context); return; } @@ -48,8 +46,6 @@ namespace Ocelot.RateLimit.Middleware if (IsWhitelisted(identity, options)) { _logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate} is white listed from rate limiting"); - await _next.Invoke(context); - await _next.Invoke(context); return; } diff --git a/test/Ocelot.ManualTest/appsettings.json b/test/Ocelot.ManualTest/appsettings.json index cb4c8665..7327a7b9 100644 --- a/test/Ocelot.ManualTest/appsettings.json +++ b/test/Ocelot.ManualTest/appsettings.json @@ -2,7 +2,7 @@ "Logging": { "IncludeScopes": true, "LogLevel": { - "Default": "Information", + "Default": "Trace", "System": "Information", "Microsoft": "Information" }