From af506b079ad851b5ef1a61515946c9afab54ae83 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Sat, 5 Nov 2016 11:36:58 +0000 Subject: [PATCH] more logging, more readme, more refactoring --- README.md | 152 +++++++++++++++--- .../Handler/AuthenticationHandler.cs | 8 +- .../Factory/AuthenticationHandlerFactory.cs | 3 +- src/Ocelot/Authentication/Handler/IHandler.cs | 10 ++ .../Handler/RequestDelegateHandler.cs | 20 +++ .../Middleware/AuthenticationMiddleware.cs | 2 +- .../Cache/Middleware/OutputCacheMiddleware.cs | 2 +- .../Middleware/ClaimsBuilderMiddleware.cs | 1 + .../DownstreamRouteFinderMiddleware.cs | 1 + .../DownstreamUrlCreatorMiddleware.cs | 2 +- .../Middleware/ExceptionHandlerMiddleware.cs | 8 +- .../HttpRequestHeadersBuilderMiddleware.cs | 29 +++- src/Ocelot/Logging/IOcelotLoggerFactory.cs | 15 +- src/Ocelot/Middleware/OcelotMiddleware.cs | 29 ++-- .../Middleware/OcelotMiddlewareExtensions.cs | 4 +- .../QueryStringBuilderMiddleware.cs | 27 +++- .../HttpRequestBuilderMiddleware.cs | 16 +- .../Middleware/RequestIdMiddleware.cs | 24 ++- .../Middleware/HttpRequesterMiddleware.cs | 15 +- .../HttpResponderMiddlewareExtensions.cs | 12 -- ...erMiddleware.cs => ResponderMiddleware.cs} | 26 ++- .../ResponderMiddlewareExtensions.cs | 12 ++ test/Ocelot.ManualTest/Startup.cs | 4 - test/Ocelot.ManualTest/appsettings.json | 2 +- test/Ocelot.ManualTest/configuration.json | 3 +- .../AuthenticationMiddlewareTests.cs | 37 +++-- .../AuthorisationMiddlewareTests.cs | 20 +-- .../Cache/OutputCacheMiddlewareTests.cs | 15 +- .../Claims/ClaimsBuilderMiddlewareTests.cs | 20 +-- .../DownstreamRouteFinderMiddlewareTests.cs | 19 +-- .../DownstreamUrlCreatorMiddlewareTests.cs | 20 +-- ...ttpRequestHeadersBuilderMiddlewareTests.cs | 13 +- .../QueryStringBuilderMiddlewareTests.cs | 11 +- .../HttpRequestBuilderMiddlewareTests.cs | 7 +- .../RequestId/RequestIdMiddlewareTests.cs | 6 +- .../Requester/HttpRequesterMiddlewareTests.cs | 8 +- ...reTests.cs => ResponderMiddlewareTests.cs} | 13 +- 37 files changed, 415 insertions(+), 201 deletions(-) create mode 100644 src/Ocelot/Authentication/Handler/IHandler.cs create mode 100644 src/Ocelot/Authentication/Handler/RequestDelegateHandler.cs delete mode 100644 src/Ocelot/Responder/Middleware/HttpResponderMiddlewareExtensions.cs rename src/Ocelot/Responder/Middleware/{HttpErrorResponderMiddleware.cs => ResponderMiddleware.cs} (65%) create mode 100644 src/Ocelot/Responder/Middleware/ResponderMiddlewareExtensions.cs rename test/Ocelot.UnitTests/Responder/{HttpErrorResponderMiddlewareTests.cs => ResponderMiddlewareTests.cs} (89%) diff --git a/README.md b/README.md index 06422a2d..329b087c 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,12 @@ to do this. ## How to install -Ocelot is designed to work with ASP.NET core only and is currently built to netcoreapp1.4 [this](https://docs.microsoft.com/en-us/dotnet/articles/standard/library) documentation may prove helpful when working out if Ocelot would be suitable for you. +Ocelot is designed to work with ASP.NET core only and is currently +built to netcoreapp1.4 [this](https://docs.microsoft.com/en-us/dotnet/articles/standard/library) documentation may prove helpful when working out if Ocelot would be suitable for you. -Install Ocelot and it's dependecies using nuget. At the moment all we have is the pre version. Once we have something working in a half decent way we will drop a version. +Install Ocelot and it's dependecies using nuget. At the moment +all we have is the pre version. Once we have something working in +a half decent way we will drop a version. `Install-Package Ocelot -Pre` @@ -36,40 +39,45 @@ and an explained configuration can be found [here](https://github.com/TomPallist ## Startup -An example startup using a json file for configuration can be seen below. Currently this is the only way to get configuration into Ocelot. +An example startup using a json file for configuration can be seen below. +Currently this is the only way to get configuration into Ocelot. - public class Startup + public class Startup { - public IConfigurationRoot Configuration { get; } - public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) - .AddJsonFile("configuration.json", optional: true, reloadOnChange: true) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddJsonFile("configuration.json") .AddEnvironmentVariables(); Configuration = builder.Build(); } - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 + + public IConfigurationRoot Configuration { get; } + public void ConfigureServices(IServiceCollection services) { + Action settings = (x) => + { + x.WithMicrosoftLogging(log => + { + log.AddConsole(LogLevel.Debug); + }) + .WithDictionaryHandle(); + }; + + services.AddOcelotOutputCaching(settings); services.AddOcelotFileConfiguration(Configuration); services.AddOcelot(); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(Configuration.GetSection("Logging")); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } app.UseOcelot(); } } @@ -77,26 +85,120 @@ An example startup using a json file for configuration can be seen below. Curren This is pretty much all you need to get going.......more to come! +## Routing + +Ocelot's primary functionality is to take incomeing http requests and forward them on +to a downstream service. At the moment in the form of another http request (in the future +this could be any transport mechanism.). + +Ocelot's describes the routing of one request to another as a ReRoute. In order to get +anything working in Ocelot you need to set up a ReRoute in the configuration. + + { + "ReRoutes": [ + ] + } + +In order to set up a ReRoute you need to add one to the json array called ReRoutes like +the following. + + { + "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", + "UpstreamTemplate": "/posts/{postId}", + "UpstreamHttpMethod": "Put" + } + +The DownstreamTemplate is the URL that this request will be forwarded to. +The UpstreamTemplate is the URL that Ocelot will use to identity which +DownstreamTemplate to use for a given request. Finally the UpstreamHttpMethod is used so +Ocelot can distinguish between requests to the same URL and is obviously needed to work :) +In Ocelot you can add placeholders for variables to your Templates in the form of {something}. +The placeholder needs to be in both the DownstreamTemplate and UpstreamTemplate. If it is +Ocelot will attempt to replace the placeholder with the correct variable value from the +Upstream URL when the request comes in. + +At the moment all Ocelot routing is case sensitive. I think I will turn this off by default +in the future with an options to make Ocelot case sensitive per ReRoute. + +## Authentication + +TBC... + +## Authorisation + +TBC... + +## Claims to Headers Tranformation + +BC... + +## Claims to Claims + +BC... + +## Claims to Query String Parameters Tranformation + +BC... + ## Logging -Ocelot uses the standard logging interfaces ILoggerFactory / ILogger at the moment. This is encapsulated in IOcelotLogger with -an implementation for the standard asp.net core logging stuff at the moment. +Ocelot uses the standard logging interfaces ILoggerFactory / ILogger at the moment. +This is encapsulated in IOcelotLogger / IOcelotLoggerFactory with an implementation +for the standard asp.net core logging stuff at the moment. + +There are a bunch of debugging logs in the ocelot middlewares however I think the +system probably needs more logging in the code it calls into. Other than the debugging +there is a global error handler that should catch any errors thrown and log them as errors. + +The reason for not just using bog standard framework logging is that I could not +work out how to override the request id that get's logged when setting IncludeScopes +to true for logging settings. Nicely onto the next feature. + +## RequestId / CorrelationId + +Ocelot supports a client sending a request id in the form of a header. If set Ocelot will +use the requestid for logging as soon as it becomes available in the middleware pipeline. +Ocelot will also forward the request id with the specified header to the downstream service. +I'm not sure if have this spot on yet in terms of the pipeline order becasue there are a few +that don't get the users request id at the moment and ocelot just logs not set for request id +which sucks. You can still get the framework request id in the logs if you set +IncludeScopes true in your logging config. + +In order to use the requestid feature in your ReRoute configuration add this setting + + "RequestIdKey": "OcRequestId" + +In this example OcRequestId is the request header that contains the clients request id. ## Caching -Ocelot supports some very rudimentary caching at the moment provider by the [CacheManager](http://cachemanager.net/) project. This is an amazing project -that is solving a lot of caching problems. I would reccomend using this package to cache with Ocelot. If you look at the example [here](https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/Startup.cs) -you can see how the cache manager is setup and then passed into the Ocelot AddOcelotOutputCaching configuration method. You can -use any settings supported by the CacheManager package and just pass them in. +Ocelot supports some very rudimentary caching at the moment provider by +the [CacheManager](http://cachemanager.net/) project. This is an amazing project +that is solving a lot of caching problems. I would reccomend using this package to +cache with Ocelot. If you look at the example [here](https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/Startup.cs) +you can see how the cache manager is setup and then passed into the Ocelot +AddOcelotOutputCaching configuration method. You can use any settings supported by +the CacheManager package and just pass them in. -Anyway Ocelot currently supports caching on the URL of the downstream service and setting a TTL in seconds to expire the cache. More to come! +Anyway Ocelot currently supports caching on the URL of the downstream service +and setting a TTL in seconds to expire the cache. More to come! + +In orde to use caching on a route in your ReRoute configuration add this setting. + + "FileCacheOptions": { "TtlSeconds": 15 } + +In this example ttl seconds is set to 15 which means the cache will expire after 15 seconds. ## Not supported Ocelot does not support... - * Chunked Encoding - Ocelot will always get the body size and return Content-Length header. Sorry - if this doesn't work for your use case! + * Chunked Encoding - Ocelot will always get the body size and return Content-Length + header. Sorry if this doesn't work for your use case! * Fowarding a host header - The host header that you send to Ocelot will not be forwarded to the downstream service. Obviously this would break everything :( +## Coming up + +You can see what we are working on [here](https://github.com/TomPallister/Ocelot/projects/1) + diff --git a/src/Ocelot/Authentication/Handler/AuthenticationHandler.cs b/src/Ocelot/Authentication/Handler/AuthenticationHandler.cs index 029147d6..3cb662b8 100644 --- a/src/Ocelot/Authentication/Handler/AuthenticationHandler.cs +++ b/src/Ocelot/Authentication/Handler/AuthenticationHandler.cs @@ -1,16 +1,14 @@ -using Microsoft.AspNetCore.Http; - -namespace Ocelot.Authentication.Handler +namespace Ocelot.Authentication.Handler { public class AuthenticationHandler { - public AuthenticationHandler(string provider, RequestDelegate handler) + public AuthenticationHandler(string provider, IHandler handler) { Provider = provider; Handler = handler; } public string Provider { get; private set; } - public RequestDelegate Handler { get; private set; } + public IHandler Handler { get; private set; } } } \ No newline at end of file diff --git a/src/Ocelot/Authentication/Handler/Factory/AuthenticationHandlerFactory.cs b/src/Ocelot/Authentication/Handler/Factory/AuthenticationHandlerFactory.cs index 46594435..6379cc1f 100644 --- a/src/Ocelot/Authentication/Handler/Factory/AuthenticationHandlerFactory.cs +++ b/src/Ocelot/Authentication/Handler/Factory/AuthenticationHandlerFactory.cs @@ -23,7 +23,8 @@ namespace Ocelot.Authentication.Handler.Factory if (!handler.IsError) { - return new OkResponse(new AuthenticationHandler(authOptions.Provider, handler.Data)); + return new OkResponse( + new AuthenticationHandler(authOptions.Provider, new RequestDelegateHandler(handler.Data))); } return new ErrorResponse(new List diff --git a/src/Ocelot/Authentication/Handler/IHandler.cs b/src/Ocelot/Authentication/Handler/IHandler.cs new file mode 100644 index 00000000..99d240e8 --- /dev/null +++ b/src/Ocelot/Authentication/Handler/IHandler.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Ocelot.Authentication.Handler +{ + public interface IHandler + { + Task Handle(HttpContext context); + } +} \ No newline at end of file diff --git a/src/Ocelot/Authentication/Handler/RequestDelegateHandler.cs b/src/Ocelot/Authentication/Handler/RequestDelegateHandler.cs new file mode 100644 index 00000000..291e8ec3 --- /dev/null +++ b/src/Ocelot/Authentication/Handler/RequestDelegateHandler.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Ocelot.Authentication.Handler +{ + public class RequestDelegateHandler : IHandler + { + private readonly RequestDelegate _requestDelegate; + + public RequestDelegateHandler(RequestDelegate requestDelegate) + { + _requestDelegate = requestDelegate; + } + + public async Task Handle(HttpContext context) + { + await _requestDelegate.Invoke(context); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs index e683b6ba..ad30e166 100644 --- a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs +++ b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs @@ -44,7 +44,7 @@ namespace Ocelot.Authentication.Middleware { _logger.LogDebug("calling authentication handler for ReRoute"); - await authenticationHandler.Data.Handler.Invoke(context); + await authenticationHandler.Data.Handler.Handle(context); } else { diff --git a/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs b/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs index 0e8a2b47..77024e70 100644 --- a/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs +++ b/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs @@ -57,7 +57,7 @@ namespace Ocelot.Cache.Middleware _logger.LogDebug("succesfully called next middleware"); - if (PipelineError()) + 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..1f6486f6 100644 --- a/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs +++ b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; using Ocelot.Middleware; diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index cdadf5a0..1aef7c7c 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; diff --git a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs index c7eae3dc..8d0af0bd 100644 --- a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Ocelot.DownstreamRouteFinder; +using Microsoft.Extensions.Logging; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; diff --git a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs index 0d989881..645652f4 100644 --- a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs +++ b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs @@ -25,10 +25,10 @@ namespace Ocelot.Errors.Middleware public async Task Invoke(HttpContext context) { try - { - _logger.LogDebug("calling middleware"); + { + _logger.LogDebug("ocelot pipeline started"); - _requestScopedDataRepository.Add("RequestId", context.TraceIdentifier); + _logger.LogDebug("calling next middleware"); await _next.Invoke(context); @@ -42,6 +42,8 @@ namespace Ocelot.Errors.Middleware _logger.LogError(message, e); await SetInternalServerErrorOnResponse(context); } + + _logger.LogDebug("ocelot pipeline finished"); } private static async Task SetInternalServerErrorOnResponse(HttpContext context) diff --git a/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs index 9bf9618a..cc262048 100644 --- a/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs +++ b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs @@ -1,7 +1,9 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Middleware; namespace Ocelot.Headers.Middleware @@ -10,24 +12,45 @@ namespace Ocelot.Headers.Middleware { private readonly RequestDelegate _next; private readonly IAddHeadersToRequest _addHeadersToRequest; + private readonly IOcelotLogger _logger; - public HttpRequestHeadersBuilderMiddleware(RequestDelegate next, + public HttpRequestHeadersBuilderMiddleware(RequestDelegate next, + IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository, IAddHeadersToRequest addHeadersToRequest) : base(requestScopedDataRepository) { _next = next; _addHeadersToRequest = addHeadersToRequest; + _logger = loggerFactory.CreateLogger(); } public async Task Invoke(HttpContext context) { + _logger.LogDebug("started calling headers builder middleware"); + if (DownstreamRoute.ReRoute.ClaimsToHeaders.Any()) { - _addHeadersToRequest.SetHeadersOnContext(DownstreamRoute.ReRoute.ClaimsToHeaders, context); + _logger.LogDebug("this route 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"); + + SetPipelineError(response.Errors); + return; + } + + _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/Logging/IOcelotLoggerFactory.cs b/src/Ocelot/Logging/IOcelotLoggerFactory.cs index b8bcf406..5305088f 100644 --- a/src/Ocelot/Logging/IOcelotLoggerFactory.cs +++ b/src/Ocelot/Logging/IOcelotLoggerFactory.cs @@ -46,21 +46,24 @@ namespace Ocelot.Logging public void LogDebug(string message, params object[] args) { - _logger.LogDebug(GetMessageWithRequestId(message), args); + _logger.LogDebug(GetMessageWithOcelotRequestId(message), args); } public void LogError(string message, Exception exception) { - _logger.LogError(GetMessageWithRequestId(message), exception); + _logger.LogError(GetMessageWithOcelotRequestId(message), exception); } - private string GetMessageWithRequestId(string message) + private string GetMessageWithOcelotRequestId(string message) { var requestId = _scopedDataRepository.Get("RequestId"); - return requestId.IsError - ? $"{message} : RequestId: Error" - : $"{message} : RequestId: {requestId.Data}"; + if (requestId != null && !requestId.IsError) + { + return $"{message} : OcelotRequestId - {requestId.Data}"; + + } + return $"{message} : OcelotRequestId - not set"; } } } diff --git a/src/Ocelot/Middleware/OcelotMiddleware.cs b/src/Ocelot/Middleware/OcelotMiddleware.cs index 16e4ff2c..0bb51040 100644 --- a/src/Ocelot/Middleware/OcelotMiddleware.cs +++ b/src/Ocelot/Middleware/OcelotMiddleware.cs @@ -15,22 +15,22 @@ namespace Ocelot.Middleware _requestScopedDataRepository = requestScopedDataRepository; } - public void SetPipelineError(List errors) + public bool PipelineError { - _requestScopedDataRepository.Add("OcelotMiddlewareError", true); - _requestScopedDataRepository.Add("OcelotMiddlewareErrors", errors); + get + { + var response = _requestScopedDataRepository.Get("OcelotMiddlewareError"); + return response.Data; + } } - public bool PipelineError() + public List PipelineErrors { - var response = _requestScopedDataRepository.Get("OcelotMiddlewareError"); - return response.Data; - } - - public List GetPipelineErrors() - { - var response = _requestScopedDataRepository.Get>("OcelotMiddlewareErrors"); - return response.Data; + get + { + var response = _requestScopedDataRepository.Get>("OcelotMiddlewareErrors"); + return response.Data; + } } public DownstreamRoute DownstreamRoute @@ -87,7 +87,12 @@ namespace Ocelot.Middleware public void SetHttpResponseMessageThisRequest(HttpResponseMessage responseMessage) { _requestScopedDataRepository.Add("HttpResponseMessage", responseMessage); + } + public void SetPipelineError(List errors) + { + _requestScopedDataRepository.Add("OcelotMiddlewareError", true); + _requestScopedDataRepository.Add("OcelotMiddlewareErrors", errors); } } } diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index 8e85413a..dfa3b3f4 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -47,7 +47,7 @@ namespace Ocelot.Middleware builder.UseIfNotNull(middlewareConfiguration.PreErrorResponderMiddleware); // This is registered first so it can catch any errors and issue an appropriate response - builder.UseHttpErrorResponderMiddleware(); + builder.UseResponderMiddleware(); // Then we get the downstream route information builder.UseDownstreamRouteFinderMiddleware(); @@ -108,7 +108,7 @@ namespace Ocelot.Middleware // Everything should now be ready to build or HttpRequest builder.UseHttpRequestBuilderMiddleware(); - //We fire off the request and set the response on the context in this middleware + //We fire off the request and set the response on the scoped data repo builder.UseHttpRequesterMiddleware(); return builder; diff --git a/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs index da308eb3..1424d713 100644 --- a/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs +++ b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs @@ -1,7 +1,9 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Middleware; namespace Ocelot.QueryStrings.Middleware @@ -10,24 +12,43 @@ namespace Ocelot.QueryStrings.Middleware { private readonly RequestDelegate _next; private readonly IAddQueriesToRequest _addQueriesToRequest; + private readonly IOcelotLogger _logger; - public QueryStringBuilderMiddleware(RequestDelegate next, + public QueryStringBuilderMiddleware(RequestDelegate next, + IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository, IAddQueriesToRequest addQueriesToRequest) : base(requestScopedDataRepository) { _next = next; _addQueriesToRequest = addQueriesToRequest; + _logger = loggerFactory.CreateLogger(); } public async Task Invoke(HttpContext context) { + _logger.LogDebug("started calling query string builder middleware"); + if (DownstreamRoute.ReRoute.ClaimsToQueries.Any()) { - _addQueriesToRequest.SetQueriesOnContext(DownstreamRoute.ReRoute.ClaimsToQueries, context); + _logger.LogDebug("this route has instructions to convert claims to queries"); + + var response = _addQueriesToRequest.SetQueriesOnContext(DownstreamRoute.ReRoute.ClaimsToQueries, context); + + if (response.IsError) + { + _logger.LogDebug("there was an error setting queries on context, setting pipeline error"); + + SetPipelineError(response.Errors); + return; + } } - + + _logger.LogDebug("calling next middleware"); + await _next.Invoke(context); + + _logger.LogDebug("succesfully called next middleware"); } } } diff --git a/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs index 1f2fea61..a2c5194b 100644 --- a/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs +++ b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Middleware; using Ocelot.Request.Builder; @@ -10,18 +12,23 @@ namespace Ocelot.Request.Middleware { private readonly RequestDelegate _next; private readonly IRequestCreator _requestCreator; + private readonly IOcelotLogger _logger; - public HttpRequestBuilderMiddleware(RequestDelegate next, + public HttpRequestBuilderMiddleware(RequestDelegate next, + IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository, IRequestCreator requestCreator) :base(requestScopedDataRepository) { _next = next; _requestCreator = requestCreator; + _logger = loggerFactory.CreateLogger(); } public async Task Invoke(HttpContext context) { + _logger.LogDebug("started calling request builder middleware"); + var buildResult = await _requestCreator .Build(context.Request.Method, DownstreamUrl, context.Request.Body, context.Request.Headers, context.Request.Cookies, context.Request.QueryString, @@ -29,13 +36,20 @@ namespace Ocelot.Request.Middleware if (buildResult.IsError) { + _logger.LogDebug("IRequestCreator returned an error, setting pipeline error"); + SetPipelineError(buildResult.Errors); return; } + _logger.LogDebug("setting upstream request"); SetUpstreamRequestForThisRequest(buildResult.Data); + _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/RequestId/Middleware/RequestIdMiddleware.cs b/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs index e6d02497..21667351 100644 --- a/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs +++ b/src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Middleware; namespace Ocelot.RequestId.Middleware @@ -10,22 +11,35 @@ namespace Ocelot.RequestId.Middleware public class RequestIdMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; + private readonly IOcelotLogger _logger; + private readonly IRequestScopedDataRepository _requestScopedDataRepository; - public RequestIdMiddleware(RequestDelegate next, + public RequestIdMiddleware(RequestDelegate next, + IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository) :base(requestScopedDataRepository) { _next = next; + _logger = loggerFactory.CreateLogger(); + _requestScopedDataRepository = requestScopedDataRepository; } public async Task Invoke(HttpContext context) - { - SetTraceIdentifier(context); + { + _logger.LogDebug("started calling request id middleware"); + + SetOcelotRequestId(context); + + _logger.LogDebug("set request id"); + + _logger.LogDebug("calling next middleware"); await _next.Invoke(context); + + _logger.LogDebug("succesfully called next middleware"); } - private void SetTraceIdentifier(HttpContext context) + private void SetOcelotRequestId(HttpContext context) { var key = DefaultRequestIdKey.Value; @@ -38,6 +52,8 @@ namespace Ocelot.RequestId.Middleware if (context.Request.Headers.TryGetValue(key, out requestId)) { + _requestScopedDataRepository.Add("RequestId", requestId.First()); + context.TraceIdentifier = requestId; } } diff --git a/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs b/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs index 3d7d37a0..f804569b 100644 --- a/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs +++ b/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Middleware; namespace Ocelot.Requester.Middleware @@ -9,27 +11,38 @@ namespace Ocelot.Requester.Middleware { private readonly RequestDelegate _next; private readonly IHttpRequester _requester; + private readonly IOcelotLogger _logger; - public HttpRequesterMiddleware(RequestDelegate next, + public HttpRequesterMiddleware(RequestDelegate next, + IOcelotLoggerFactory loggerFactory, IHttpRequester requester, IRequestScopedDataRepository requestScopedDataRepository) :base(requestScopedDataRepository) { _next = next; _requester = requester; + _logger = loggerFactory.CreateLogger(); } public async Task Invoke(HttpContext context) { + _logger.LogDebug("started calling requester middleware"); + var response = await _requester.GetResponse(Request); if (response.IsError) { + _logger.LogDebug("IHttpRequester returned an error, setting pipeline error"); + SetPipelineError(response.Errors); return; } + _logger.LogDebug("setting http response message"); + SetHttpResponseMessageThisRequest(response.Data); + + _logger.LogDebug("returning to calling middleware"); } } } \ No newline at end of file diff --git a/src/Ocelot/Responder/Middleware/HttpResponderMiddlewareExtensions.cs b/src/Ocelot/Responder/Middleware/HttpResponderMiddlewareExtensions.cs deleted file mode 100644 index aad14839..00000000 --- a/src/Ocelot/Responder/Middleware/HttpResponderMiddlewareExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Builder; - -namespace Ocelot.Responder.Middleware -{ - public static class HttpResponderMiddlewareExtensions - { - public static IApplicationBuilder UseHttpErrorResponderMiddleware(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } - } -} \ No newline at end of file diff --git a/src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs similarity index 65% rename from src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs rename to src/Ocelot/Responder/Middleware/ResponderMiddleware.cs index 1cf14227..06da92dc 100644 --- a/src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs +++ b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs @@ -1,20 +1,24 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Ocelot.Errors; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Middleware; namespace Ocelot.Responder.Middleware { - public class HttpErrorResponderMiddleware : OcelotMiddleware + public class ResponderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IHttpResponder _responder; private readonly IErrorsToHttpStatusCodeMapper _codeMapper; + private readonly IOcelotLogger _logger; - public HttpErrorResponderMiddleware(RequestDelegate next, + public ResponderMiddleware(RequestDelegate next, IHttpResponder responder, + IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository, IErrorsToHttpStatusCodeMapper codeMapper) :base(requestScopedDataRepository) @@ -22,24 +26,38 @@ namespace Ocelot.Responder.Middleware _next = next; _responder = responder; _codeMapper = codeMapper; + _logger = loggerFactory.CreateLogger(); + } public async Task Invoke(HttpContext context) { + _logger.LogDebug("started error responder middleware"); + await _next.Invoke(context); - if (PipelineError()) + _logger.LogDebug("calling next middleware"); + + if (PipelineError) { - var errors = GetPipelineErrors(); + _logger.LogDebug("there is a pipeline error, getting errors"); + + var errors = PipelineErrors; + + _logger.LogDebug("received errors setting error response"); await SetErrorResponse(context, errors); } else { + _logger.LogDebug("no pipeline error, setting response"); + var setResponse = await _responder.SetResponseOnHttpContext(context, HttpResponseMessage); if (setResponse.IsError) { + _logger.LogDebug("error setting response, returning error to client"); + await SetErrorResponse(context, setResponse.Errors); } } diff --git a/src/Ocelot/Responder/Middleware/ResponderMiddlewareExtensions.cs b/src/Ocelot/Responder/Middleware/ResponderMiddlewareExtensions.cs new file mode 100644 index 00000000..5c119e69 --- /dev/null +++ b/src/Ocelot/Responder/Middleware/ResponderMiddlewareExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Builder; + +namespace Ocelot.Responder.Middleware +{ + public static class ResponderMiddlewareExtensions + { + public static IApplicationBuilder UseResponderMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/test/Ocelot.ManualTest/Startup.cs b/test/Ocelot.ManualTest/Startup.cs index d202cc3e..70448fcf 100644 --- a/test/Ocelot.ManualTest/Startup.cs +++ b/test/Ocelot.ManualTest/Startup.cs @@ -27,7 +27,6 @@ namespace Ocelot.ManualTest public IConfigurationRoot Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { Action settings = (x) => @@ -44,13 +43,10 @@ namespace Ocelot.ManualTest services.AddOcelot(); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); - loggerFactory.AddDebug(); - app.UseOcelot(); } } diff --git a/test/Ocelot.ManualTest/appsettings.json b/test/Ocelot.ManualTest/appsettings.json index fa8ce71a..d73b7dcb 100644 --- a/test/Ocelot.ManualTest/appsettings.json +++ b/test/Ocelot.ManualTest/appsettings.json @@ -1,6 +1,6 @@ { "Logging": { - "IncludeScopes": false, + "IncludeScopes": true, "LogLevel": { "Default": "Debug", "System": "Information", diff --git a/test/Ocelot.ManualTest/configuration.json b/test/Ocelot.ManualTest/configuration.json index 8d027770..0caf2943 100644 --- a/test/Ocelot.ManualTest/configuration.json +++ b/test/Ocelot.ManualTest/configuration.json @@ -41,7 +41,8 @@ "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts", "UpstreamTemplate": "/posts", "UpstreamHttpMethod": "Get", - "FileCacheOptions": { "TtlSeconds": 15 } + "FileCacheOptions": { "TtlSeconds": 15 }, + "RequestIdKey": "OcRequestId" }, { "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", diff --git a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs index 3286f6e1..ff467aa7 100644 --- a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs @@ -2,19 +2,25 @@ using System.Collections.Generic; using System.IO; using System.Net.Http; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; +using Ocelot.Authentication.Handler; using Ocelot.Authentication.Handler.Factory; using Ocelot.Authentication.Middleware; using Ocelot.Cache.Middleware; +using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; using Ocelot.Responses; +using Shouldly; using TestStack.BDDfy; using Xunit; @@ -29,19 +35,17 @@ namespace Ocelot.UnitTests.Authentication private readonly HttpClient _client; private HttpResponseMessage _result; private OkResponse _downstreamRoute; - private Mock _mockLoggerFactory; public AuthenticationMiddlewareTests() { _url = "http://localhost:51879"; _scopedRepository = new Mock(); _authFactory = new Mock(); - SetUpLogger(); - var builder = new WebHostBuilder() .ConfigureServices(x => { - x.AddSingleton(_mockLoggerFactory.Object); + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_authFactory.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -53,6 +57,11 @@ namespace Ocelot.UnitTests.Authentication .Configure(app => { app.UseAuthenticationMiddleware(); + + app.Run(async x => + { + await x.Response.WriteAsync("The user is authenticated"); + }); }); _server = new TestServer(builder); @@ -60,28 +69,18 @@ namespace Ocelot.UnitTests.Authentication } [Fact] - public void happy_path() + public void should_call_next_middleware_if_route_is_not_authenticated() { this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List(), new ReRouteBuilder().Build()))) .When(x => x.WhenICallTheMiddleware()) - .Then(x => x.ThenNoExceptionsAreThrown()) + .Then(x => x.ThenTheUserIsAuthenticated()) .BDDfy(); } - private void SetUpLogger() + private void ThenTheUserIsAuthenticated() { - _mockLoggerFactory = new Mock(); - - var logger = new Mock(); - - _mockLoggerFactory - .Setup(x => x.CreateLogger()) - .Returns(logger.Object); - } - - private void ThenNoExceptionsAreThrown() - { - //todo not suck + var content = _result.Content.ReadAsStringAsync().Result; + content.ShouldBe("The user is authenticated"); } private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) diff --git a/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs b/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs index e6e25057..8d681e03 100644 --- a/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs @@ -6,9 +6,9 @@ using System.Security.Claims; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Authorisation; -using Ocelot.Cache.Middleware; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; @@ -31,19 +31,18 @@ namespace Ocelot.UnitTests.Authorization private readonly HttpClient _client; private HttpResponseMessage _result; private OkResponse _downstreamRoute; - private Mock _mockLoggerFactory; public AuthorisationMiddlewareTests() { _url = "http://localhost:51879"; _scopedRepository = new Mock(); _authService = new Mock(); - SetUpLogger(); var builder = new WebHostBuilder() .ConfigureServices(x => { - x.AddSingleton(_mockLoggerFactory.Object); + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_authService.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -62,7 +61,7 @@ namespace Ocelot.UnitTests.Authorization } [Fact] - public void happy_path() + public void should_call_authorisation_service() { this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List(), new ReRouteBuilder().WithIsAuthorised(true).Build()))) .And(x => x.GivenTheAuthServiceReturns(new OkResponse(true))) @@ -71,17 +70,6 @@ namespace Ocelot.UnitTests.Authorization .BDDfy(); } - private void SetUpLogger() - { - _mockLoggerFactory = new Mock(); - - var logger = new Mock(); - - _mockLoggerFactory - .Setup(x => x.CreateLogger()) - .Returns(logger.Object); - } - private void GivenTheAuthServiceReturns(Response expected) { _authService diff --git a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs index 541ef880..9190dbe9 100644 --- a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs @@ -6,6 +6,7 @@ using CacheManager.Core; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Cache; using Ocelot.Cache.Middleware; @@ -25,7 +26,6 @@ namespace Ocelot.UnitTests.Cache { private readonly Mock> _cacheManager; private readonly Mock _scopedRepo; - private Mock _mockLoggerFactory; private readonly string _url; private readonly TestServer _server; private readonly HttpClient _client; @@ -37,14 +37,13 @@ namespace Ocelot.UnitTests.Cache _cacheManager = new Mock>(); _scopedRepo = new Mock(); - SetUpLogger(); _url = "http://localhost:51879"; var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); x.AddLogging(); - x.AddSingleton(_mockLoggerFactory.Object); x.AddSingleton(_cacheManager.Object); x.AddSingleton(_scopedRepo.Object); }) @@ -85,16 +84,6 @@ namespace Ocelot.UnitTests.Cache .BDDfy(); } - private void SetUpLogger() - { - _mockLoggerFactory = new Mock(); - - var logger = new Mock(); - - _mockLoggerFactory - .Setup(x => x.CreateLogger()) - .Returns(logger.Object); - } private void GivenTheDownstreamRouteIs() { diff --git a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs index 8031e232..e3cccdc0 100644 --- a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Cache.Middleware; using Ocelot.Claims; @@ -31,19 +32,19 @@ namespace Ocelot.UnitTests.Claims private readonly HttpClient _client; private Response _downstreamRoute; private HttpResponseMessage _result; - private Mock _mockLoggerFactory; public ClaimsBuilderMiddlewareTests() { _url = "http://localhost:51879"; _scopedRepository = new Mock(); _addHeaders = new Mock(); - SetUpLogger(); var builder = new WebHostBuilder() .ConfigureServices(x => { - x.AddSingleton(_mockLoggerFactory.Object); + x.AddSingleton(); + + x.AddLogging(); x.AddSingleton(_addHeaders.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -62,7 +63,7 @@ namespace Ocelot.UnitTests.Claims } [Fact] - public void happy_path() + public void should_call_claims_to_request_correctly() { var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() @@ -80,17 +81,6 @@ namespace Ocelot.UnitTests.Claims .BDDfy(); } - private void SetUpLogger() - { - _mockLoggerFactory = new Mock(); - - var logger = new Mock(); - - _mockLoggerFactory - .Setup(x => x.CreateLogger()) - .Returns(logger.Object); - } - private void GivenTheAddClaimsToRequestReturns() { _addHeaders diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs index 87eb6613..22dfea80 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs @@ -5,8 +5,8 @@ using System.Net.Http; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; -using Ocelot.Claims.Middleware; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.Finder; @@ -29,19 +29,18 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder private readonly HttpClient _client; private Response _downstreamRoute; private HttpResponseMessage _result; - private Mock _mockLoggerFactory; public DownstreamRouteFinderMiddlewareTests() { _url = "http://localhost:51879"; _downstreamRouteFinder = new Mock(); _scopedRepository = new Mock(); - SetUpLogger(); var builder = new WebHostBuilder() .ConfigureServices(x => { - x.AddSingleton(_mockLoggerFactory.Object); + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_downstreamRouteFinder.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -60,7 +59,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder } [Fact] - public void happy_path() + public void should_call_scoped_data_repository_correctly() { this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build()))) .When(x => x.WhenICallTheMiddleware()) @@ -68,16 +67,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .BDDfy(); } - private void SetUpLogger() - { - _mockLoggerFactory = new Mock(); - - var logger = new Mock(); - - _mockLoggerFactory - .Setup(x => x.CreateLogger()) - .Returns(logger.Object); - } private void ThenTheScopedDataRepositoryIsCalledCorrectly() { diff --git a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs index 0e9d375e..98bc5f0b 100644 --- a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs @@ -5,6 +5,7 @@ using System.Net.Http; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; @@ -30,19 +31,18 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator private Response _downstreamRoute; private HttpResponseMessage _result; private OkResponse _downstreamUrl; - private Mock _mockLoggerFactory; public DownstreamUrlCreatorMiddlewareTests() { _url = "http://localhost:51879"; _downstreamUrlTemplateVariableReplacer = new Mock(); _scopedRepository = new Mock(); - SetUpLogger(); var builder = new WebHostBuilder() .ConfigureServices(x => { - x.AddSingleton(_mockLoggerFactory.Object); + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -61,7 +61,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator } [Fact] - public void happy_path() + public void should_call_scoped_data_repository_correctly() { this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build()))) .And(x => x.TheUrlReplacerReturns("any old string")) @@ -70,18 +70,6 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator .BDDfy(); } - - private void SetUpLogger() - { - _mockLoggerFactory = new Mock(); - - var logger = new Mock(); - - _mockLoggerFactory - .Setup(x => x.CreateLogger()) - .Returns(logger.Object); - } - private void TheUrlReplacerReturns(string downstreamUrl) { _downstreamUrl = new OkResponse(new DownstreamUrl(downstreamUrl)); diff --git a/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs index e6b6c068..b85802af 100644 --- a/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs @@ -6,14 +6,17 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; +using Ocelot.DownstreamUrlCreator.Middleware; using Ocelot.Headers; using Ocelot.Headers.Middleware; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Responses; using TestStack.BDDfy; using Xunit; @@ -35,9 +38,13 @@ namespace Ocelot.UnitTests.Headers _url = "http://localhost:51879"; _scopedRepository = new Mock(); _addHeaders = new Mock(); + + var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_addHeaders.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -56,7 +63,7 @@ namespace Ocelot.UnitTests.Headers } [Fact] - public void happy_path() + public void should_call_add_headers_to_request_correctly() { var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() @@ -68,13 +75,13 @@ namespace Ocelot.UnitTests.Headers .Build()); this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) - .And(x => x.GivenTheAddHeadersToRequestReturns("123")) + .And(x => x.GivenTheAddHeadersToRequestReturns()) .When(x => x.WhenICallTheMiddleware()) .Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly()) .BDDfy(); } - private void GivenTheAddHeadersToRequestReturns(string claimValue) + private void GivenTheAddHeadersToRequestReturns() { _addHeaders .Setup(x => x.SetHeadersOnContext(It.IsAny>(), diff --git a/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs index 0a481731..e4c7375e 100644 --- a/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs @@ -6,12 +6,15 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; +using Ocelot.Headers.Middleware; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.QueryStrings; using Ocelot.QueryStrings.Middleware; using Ocelot.Responses; @@ -38,6 +41,8 @@ namespace Ocelot.UnitTests.QueryStrings var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_addQueries.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -56,7 +61,7 @@ namespace Ocelot.UnitTests.QueryStrings } [Fact] - public void happy_path() + public void should_call_add_queries_correctly() { var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() @@ -70,7 +75,7 @@ namespace Ocelot.UnitTests.QueryStrings this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) .And(x => x.GivenTheAddHeadersToRequestReturns()) .When(x => x.WhenICallTheMiddleware()) - .Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly()) + .Then(x => x.ThenTheAddQueriesToRequestIsCalledCorrectly()) .BDDfy(); } @@ -82,7 +87,7 @@ namespace Ocelot.UnitTests.QueryStrings .Returns(new OkResponse()); } - private void ThenTheAddHeadersToRequestIsCalledCorrectly() + private void ThenTheAddQueriesToRequestIsCalledCorrectly() { _addQueries .Verify(x => x.SetQueriesOnContext(It.IsAny>(), diff --git a/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs index a4797bcb..e2f81abe 100644 --- a/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs @@ -7,11 +7,13 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Request.Builder; using Ocelot.Request.Middleware; using Ocelot.Responses; @@ -37,10 +39,11 @@ namespace Ocelot.UnitTests.Request _url = "http://localhost:51879"; _requestBuilder = new Mock(); _scopedRepository = new Mock(); - var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_requestBuilder.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -59,7 +62,7 @@ namespace Ocelot.UnitTests.Request } [Fact] - public void happy_path() + public void should_call_scoped_data_repository_correctly() { var downstreamRoute = new DownstreamRoute(new List(), diff --git a/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs b/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs index 6edaabc5..8c023783 100644 --- a/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs @@ -8,11 +8,14 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; +using Ocelot.Request.Middleware; using Ocelot.RequestId.Middleware; using Ocelot.Responses; using Shouldly; @@ -36,10 +39,11 @@ namespace Ocelot.UnitTests.RequestId { _url = "http://localhost:51879"; _scopedRepository = new Mock(); - var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_scopedRepository.Object); }) .UseUrls(_url) diff --git a/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs b/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs index 0c570713..d99a99eb 100644 --- a/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs @@ -6,8 +6,11 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; +using Ocelot.QueryStrings.Middleware; using Ocelot.Requester; using Ocelot.Requester.Middleware; using Ocelot.Responder; @@ -33,10 +36,11 @@ namespace Ocelot.UnitTests.Requester _url = "http://localhost:51879"; _requester = new Mock(); _scopedRepository = new Mock(); - var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_requester.Object); x.AddSingleton(_scopedRepository.Object); }) @@ -55,7 +59,7 @@ namespace Ocelot.UnitTests.Requester } [Fact] - public void happy_path() + public void should_call_scoped_data_repository_correctly() { this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),new CookieContainer()))) .And(x => x.GivenTheRequesterReturns(new HttpResponseMessage())) diff --git a/test/Ocelot.UnitTests/Responder/HttpErrorResponderMiddlewareTests.cs b/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs similarity index 89% rename from test/Ocelot.UnitTests/Responder/HttpErrorResponderMiddlewareTests.cs rename to test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs index 61d260dd..b643028e 100644 --- a/test/Ocelot.UnitTests/Responder/HttpErrorResponderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs @@ -5,8 +5,10 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Ocelot.Infrastructure.RequestData; +using Ocelot.Logging; using Ocelot.Responder; using Ocelot.Responder.Middleware; using Ocelot.Responses; @@ -15,7 +17,7 @@ using Xunit; namespace Ocelot.UnitTests.Responder { - public class HttpErrorResponderMiddlewareTests : IDisposable + public class ResponderMiddlewareTests : IDisposable { private readonly Mock _responder; private readonly Mock _scopedRepository; @@ -26,16 +28,17 @@ namespace Ocelot.UnitTests.Responder private HttpResponseMessage _result; private OkResponse _response; - public HttpErrorResponderMiddlewareTests() + public ResponderMiddlewareTests() { _url = "http://localhost:51879"; _responder = new Mock(); _scopedRepository = new Mock(); _codeMapper = new Mock(); - var builder = new WebHostBuilder() .ConfigureServices(x => { + x.AddSingleton(); + x.AddLogging(); x.AddSingleton(_codeMapper.Object); x.AddSingleton(_responder.Object); x.AddSingleton(_scopedRepository.Object); @@ -47,7 +50,7 @@ namespace Ocelot.UnitTests.Responder .UseUrls(_url) .Configure(app => { - app.UseHttpErrorResponderMiddleware(); + app.UseResponderMiddleware(); }); _server = new TestServer(builder); @@ -55,7 +58,7 @@ namespace Ocelot.UnitTests.Responder } [Fact] - public void happy_path() + public void should_not_return_any_errors() { this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage())) .And(x => x.GivenThereAreNoPipelineErrors())