more logging, more readme, more refactoring

This commit is contained in:
TomPallister 2016-11-05 11:36:58 +00:00
parent 8582ba45a9
commit af506b079a
37 changed files with 415 additions and 201 deletions

148
README.md
View File

@ -21,9 +21,12 @@ to do this.
## How to install ## 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` `Install-Package Ocelot -Pre`
@ -36,40 +39,45 @@ and an explained configuration can be found [here](https://github.com/TomPallist
## Startup ## 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) public Startup(IHostingEnvironment env)
{ {
var builder = new ConfigurationBuilder() var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath) .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($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("configuration.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
Configuration = builder.Build(); 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) public void ConfigureServices(IServiceCollection services)
{ {
Action<ConfigurationBuilderCachePart> settings = (x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
services.AddOcelotOutputCaching(settings);
services.AddOcelotFileConfiguration(Configuration); services.AddOcelotFileConfiguration(Configuration);
services.AddOcelot(); 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) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
loggerFactory.AddConsole(); loggerFactory.AddConsole(Configuration.GetSection("Logging"));
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseOcelot(); 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! 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 ## Logging
Ocelot uses the standard logging interfaces ILoggerFactory / ILogger<T> at the moment. This is encapsulated in IOcelotLogger with Ocelot uses the standard logging interfaces ILoggerFactory / ILogger<T> at the moment.
an implementation for the standard asp.net core logging stuff 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 ## Caching
Ocelot supports some very rudimentary caching at the moment provider by the [CacheManager](http://cachemanager.net/) project. This is an amazing project Ocelot supports some very rudimentary caching at the moment provider by
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) the [CacheManager](http://cachemanager.net/) project. This is an amazing project
you can see how the cache manager is setup and then passed into the Ocelot AddOcelotOutputCaching configuration method. You can that is solving a lot of caching problems. I would reccomend using this package to
use any settings supported by the CacheManager package and just pass them in. 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 ## Not supported
Ocelot does not support... Ocelot does not support...
* Chunked Encoding - Ocelot will always get the body size and return Content-Length header. Sorry * Chunked Encoding - Ocelot will always get the body size and return Content-Length
if this doesn't work for your use case! 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 * 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 :( 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)

View File

@ -1,16 +1,14 @@
using Microsoft.AspNetCore.Http; namespace Ocelot.Authentication.Handler
namespace Ocelot.Authentication.Handler
{ {
public class AuthenticationHandler public class AuthenticationHandler
{ {
public AuthenticationHandler(string provider, RequestDelegate handler) public AuthenticationHandler(string provider, IHandler handler)
{ {
Provider = provider; Provider = provider;
Handler = handler; Handler = handler;
} }
public string Provider { get; private set; } public string Provider { get; private set; }
public RequestDelegate Handler { get; private set; } public IHandler Handler { get; private set; }
} }
} }

View File

@ -23,7 +23,8 @@ namespace Ocelot.Authentication.Handler.Factory
if (!handler.IsError) if (!handler.IsError)
{ {
return new OkResponse<AuthenticationHandler>(new AuthenticationHandler(authOptions.Provider, handler.Data)); return new OkResponse<AuthenticationHandler>(
new AuthenticationHandler(authOptions.Provider, new RequestDelegateHandler(handler.Data)));
} }
return new ErrorResponse<AuthenticationHandler>(new List<Error> return new ErrorResponse<AuthenticationHandler>(new List<Error>

View File

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Ocelot.Authentication.Handler
{
public interface IHandler
{
Task Handle(HttpContext context);
}
}

View File

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

View File

@ -44,7 +44,7 @@ namespace Ocelot.Authentication.Middleware
{ {
_logger.LogDebug("calling authentication handler for ReRoute"); _logger.LogDebug("calling authentication handler for ReRoute");
await authenticationHandler.Data.Handler.Invoke(context); await authenticationHandler.Data.Handler.Handle(context);
} }
else else
{ {

View File

@ -57,7 +57,7 @@ namespace Ocelot.Cache.Middleware
_logger.LogDebug("succesfully called next middleware"); _logger.LogDebug("succesfully called next middleware");
if (PipelineError()) if (PipelineError)
{ {
_logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey); _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey);

View File

@ -1,6 +1,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;

View File

@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;

View File

@ -1,6 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder; using Microsoft.Extensions.Logging;
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;

View File

@ -26,9 +26,9 @@ namespace Ocelot.Errors.Middleware
{ {
try try
{ {
_logger.LogDebug("calling middleware"); _logger.LogDebug("ocelot pipeline started");
_requestScopedDataRepository.Add("RequestId", context.TraceIdentifier); _logger.LogDebug("calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
@ -42,6 +42,8 @@ namespace Ocelot.Errors.Middleware
_logger.LogError(message, e); _logger.LogError(message, e);
await SetInternalServerErrorOnResponse(context); await SetInternalServerErrorOnResponse(context);
} }
_logger.LogDebug("ocelot pipeline finished");
} }
private static async Task SetInternalServerErrorOnResponse(HttpContext context) private static async Task SetInternalServerErrorOnResponse(HttpContext context)

View File

@ -1,7 +1,9 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Headers.Middleware namespace Ocelot.Headers.Middleware
@ -10,24 +12,45 @@ namespace Ocelot.Headers.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IAddHeadersToRequest _addHeadersToRequest; private readonly IAddHeadersToRequest _addHeadersToRequest;
private readonly IOcelotLogger _logger;
public HttpRequestHeadersBuilderMiddleware(RequestDelegate next, public HttpRequestHeadersBuilderMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IAddHeadersToRequest addHeadersToRequest) IAddHeadersToRequest addHeadersToRequest)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_addHeadersToRequest = addHeadersToRequest; _addHeadersToRequest = addHeadersToRequest;
_logger = loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started calling headers builder middleware");
if (DownstreamRoute.ReRoute.ClaimsToHeaders.Any()) 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); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }
} }

View File

@ -46,21 +46,24 @@ namespace Ocelot.Logging
public void LogDebug(string message, params object[] args) 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) 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<string>("RequestId"); var requestId = _scopedDataRepository.Get<string>("RequestId");
return requestId.IsError if (requestId != null && !requestId.IsError)
? $"{message} : RequestId: Error" {
: $"{message} : RequestId: {requestId.Data}"; return $"{message} : OcelotRequestId - {requestId.Data}";
}
return $"{message} : OcelotRequestId - not set";
} }
} }
} }

View File

@ -15,23 +15,23 @@ namespace Ocelot.Middleware
_requestScopedDataRepository = requestScopedDataRepository; _requestScopedDataRepository = requestScopedDataRepository;
} }
public void SetPipelineError(List<Error> errors) public bool PipelineError
{ {
_requestScopedDataRepository.Add("OcelotMiddlewareError", true); get
_requestScopedDataRepository.Add("OcelotMiddlewareErrors", errors);
}
public bool PipelineError()
{ {
var response = _requestScopedDataRepository.Get<bool>("OcelotMiddlewareError"); var response = _requestScopedDataRepository.Get<bool>("OcelotMiddlewareError");
return response.Data; return response.Data;
} }
}
public List<Error> GetPipelineErrors() public List<Error> PipelineErrors
{
get
{ {
var response = _requestScopedDataRepository.Get<List<Error>>("OcelotMiddlewareErrors"); var response = _requestScopedDataRepository.Get<List<Error>>("OcelotMiddlewareErrors");
return response.Data; return response.Data;
} }
}
public DownstreamRoute DownstreamRoute public DownstreamRoute DownstreamRoute
{ {
@ -87,7 +87,12 @@ namespace Ocelot.Middleware
public void SetHttpResponseMessageThisRequest(HttpResponseMessage responseMessage) public void SetHttpResponseMessageThisRequest(HttpResponseMessage responseMessage)
{ {
_requestScopedDataRepository.Add("HttpResponseMessage", responseMessage); _requestScopedDataRepository.Add("HttpResponseMessage", responseMessage);
}
public void SetPipelineError(List<Error> errors)
{
_requestScopedDataRepository.Add("OcelotMiddlewareError", true);
_requestScopedDataRepository.Add("OcelotMiddlewareErrors", errors);
} }
} }
} }

View File

@ -47,7 +47,7 @@ namespace Ocelot.Middleware
builder.UseIfNotNull(middlewareConfiguration.PreErrorResponderMiddleware); builder.UseIfNotNull(middlewareConfiguration.PreErrorResponderMiddleware);
// This is registered first so it can catch any errors and issue an appropriate response // 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 // Then we get the downstream route information
builder.UseDownstreamRouteFinderMiddleware(); builder.UseDownstreamRouteFinderMiddleware();
@ -108,7 +108,7 @@ namespace Ocelot.Middleware
// Everything should now be ready to build or HttpRequest // Everything should now be ready to build or HttpRequest
builder.UseHttpRequestBuilderMiddleware(); 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(); builder.UseHttpRequesterMiddleware();
return builder; return builder;

View File

@ -1,7 +1,9 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.QueryStrings.Middleware namespace Ocelot.QueryStrings.Middleware
@ -10,24 +12,43 @@ namespace Ocelot.QueryStrings.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IAddQueriesToRequest _addQueriesToRequest; private readonly IAddQueriesToRequest _addQueriesToRequest;
private readonly IOcelotLogger _logger;
public QueryStringBuilderMiddleware(RequestDelegate next, public QueryStringBuilderMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IAddQueriesToRequest addQueriesToRequest) IAddQueriesToRequest addQueriesToRequest)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_addQueriesToRequest = addQueriesToRequest; _addQueriesToRequest = addQueriesToRequest;
_logger = loggerFactory.CreateLogger<QueryStringBuilderMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started calling query string builder middleware");
if (DownstreamRoute.ReRoute.ClaimsToQueries.Any()) 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); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }
} }

View File

@ -1,6 +1,8 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
using Ocelot.Request.Builder; using Ocelot.Request.Builder;
@ -10,18 +12,23 @@ namespace Ocelot.Request.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IRequestCreator _requestCreator; private readonly IRequestCreator _requestCreator;
private readonly IOcelotLogger _logger;
public HttpRequestBuilderMiddleware(RequestDelegate next, public HttpRequestBuilderMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IRequestCreator requestCreator) IRequestCreator requestCreator)
:base(requestScopedDataRepository) :base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_requestCreator = requestCreator; _requestCreator = requestCreator;
_logger = loggerFactory.CreateLogger<HttpRequestBuilderMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started calling request builder middleware");
var buildResult = await _requestCreator var buildResult = await _requestCreator
.Build(context.Request.Method, DownstreamUrl, context.Request.Body, .Build(context.Request.Method, DownstreamUrl, context.Request.Body,
context.Request.Headers, context.Request.Cookies, context.Request.QueryString, context.Request.Headers, context.Request.Cookies, context.Request.QueryString,
@ -29,13 +36,20 @@ namespace Ocelot.Request.Middleware
if (buildResult.IsError) if (buildResult.IsError)
{ {
_logger.LogDebug("IRequestCreator returned an error, setting pipeline error");
SetPipelineError(buildResult.Errors); SetPipelineError(buildResult.Errors);
return; return;
} }
_logger.LogDebug("setting upstream request");
SetUpstreamRequestForThisRequest(buildResult.Data); SetUpstreamRequestForThisRequest(buildResult.Data);
_logger.LogDebug("calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }
} }

View File

@ -3,6 +3,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.RequestId.Middleware namespace Ocelot.RequestId.Middleware
@ -10,22 +11,35 @@ namespace Ocelot.RequestId.Middleware
public class RequestIdMiddleware : OcelotMiddleware public class RequestIdMiddleware : OcelotMiddleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
public RequestIdMiddleware(RequestDelegate next, public RequestIdMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository) IRequestScopedDataRepository requestScopedDataRepository)
:base(requestScopedDataRepository) :base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<RequestIdMiddleware>();
_requestScopedDataRepository = requestScopedDataRepository;
} }
public async Task Invoke(HttpContext context) 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); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
private void SetTraceIdentifier(HttpContext context) private void SetOcelotRequestId(HttpContext context)
{ {
var key = DefaultRequestIdKey.Value; var key = DefaultRequestIdKey.Value;
@ -38,6 +52,8 @@ namespace Ocelot.RequestId.Middleware
if (context.Request.Headers.TryGetValue(key, out requestId)) if (context.Request.Headers.TryGetValue(key, out requestId))
{ {
_requestScopedDataRepository.Add("RequestId", requestId.First());
context.TraceIdentifier = requestId; context.TraceIdentifier = requestId;
} }
} }

View File

@ -1,6 +1,8 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Requester.Middleware namespace Ocelot.Requester.Middleware
@ -9,27 +11,38 @@ namespace Ocelot.Requester.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IHttpRequester _requester; private readonly IHttpRequester _requester;
private readonly IOcelotLogger _logger;
public HttpRequesterMiddleware(RequestDelegate next, public HttpRequesterMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IHttpRequester requester, IHttpRequester requester,
IRequestScopedDataRepository requestScopedDataRepository) IRequestScopedDataRepository requestScopedDataRepository)
:base(requestScopedDataRepository) :base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_requester = requester; _requester = requester;
_logger = loggerFactory.CreateLogger<HttpRequesterMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started calling requester middleware");
var response = await _requester.GetResponse(Request); var response = await _requester.GetResponse(Request);
if (response.IsError) if (response.IsError)
{ {
_logger.LogDebug("IHttpRequester returned an error, setting pipeline error");
SetPipelineError(response.Errors); SetPipelineError(response.Errors);
return; return;
} }
_logger.LogDebug("setting http response message");
SetHttpResponseMessageThisRequest(response.Data); SetHttpResponseMessageThisRequest(response.Data);
_logger.LogDebug("returning to calling middleware");
} }
} }
} }

View File

@ -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<HttpErrorResponderMiddleware>();
}
}
}

View File

@ -1,20 +1,24 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Responder.Middleware namespace Ocelot.Responder.Middleware
{ {
public class HttpErrorResponderMiddleware : OcelotMiddleware public class ResponderMiddleware : OcelotMiddleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IHttpResponder _responder; private readonly IHttpResponder _responder;
private readonly IErrorsToHttpStatusCodeMapper _codeMapper; private readonly IErrorsToHttpStatusCodeMapper _codeMapper;
private readonly IOcelotLogger _logger;
public HttpErrorResponderMiddleware(RequestDelegate next, public ResponderMiddleware(RequestDelegate next,
IHttpResponder responder, IHttpResponder responder,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IErrorsToHttpStatusCodeMapper codeMapper) IErrorsToHttpStatusCodeMapper codeMapper)
:base(requestScopedDataRepository) :base(requestScopedDataRepository)
@ -22,24 +26,38 @@ namespace Ocelot.Responder.Middleware
_next = next; _next = next;
_responder = responder; _responder = responder;
_codeMapper = codeMapper; _codeMapper = codeMapper;
_logger = loggerFactory.CreateLogger<ResponderMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started error responder middleware");
await _next.Invoke(context); 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); await SetErrorResponse(context, errors);
} }
else else
{ {
_logger.LogDebug("no pipeline error, setting response");
var setResponse = await _responder.SetResponseOnHttpContext(context, HttpResponseMessage); var setResponse = await _responder.SetResponseOnHttpContext(context, HttpResponseMessage);
if (setResponse.IsError) if (setResponse.IsError)
{ {
_logger.LogDebug("error setting response, returning error to client");
await SetErrorResponse(context, setResponse.Errors); await SetErrorResponse(context, setResponse.Errors);
} }
} }

View File

@ -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<ResponderMiddleware>();
}
}
}

View File

@ -27,7 +27,6 @@ namespace Ocelot.ManualTest
public IConfigurationRoot Configuration { get; } 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) public void ConfigureServices(IServiceCollection services)
{ {
Action<ConfigurationBuilderCachePart> settings = (x) => Action<ConfigurationBuilderCachePart> settings = (x) =>
@ -44,13 +43,10 @@ namespace Ocelot.ManualTest
services.AddOcelot(); 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) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseOcelot(); app.UseOcelot();
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"Logging": { "Logging": {
"IncludeScopes": false, "IncludeScopes": true,
"LogLevel": { "LogLevel": {
"Default": "Debug", "Default": "Debug",
"System": "Information", "System": "Information",

View File

@ -41,7 +41,8 @@
"DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts", "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts",
"UpstreamTemplate": "/posts", "UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 },
"RequestIdKey": "OcRequestId"
}, },
{ {
"DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}",

View File

@ -2,19 +2,25 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Authentication.Handler;
using Ocelot.Authentication.Handler.Factory; using Ocelot.Authentication.Handler.Factory;
using Ocelot.Authentication.Middleware; using Ocelot.Authentication.Middleware;
using Ocelot.Cache.Middleware; using Ocelot.Cache.Middleware;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -29,19 +35,17 @@ namespace Ocelot.UnitTests.Authentication
private readonly HttpClient _client; private readonly HttpClient _client;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<DownstreamRoute> _downstreamRoute; private OkResponse<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public AuthenticationMiddlewareTests() public AuthenticationMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_authFactory = new Mock<IAuthenticationHandlerFactory>(); _authFactory = new Mock<IAuthenticationHandlerFactory>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object); x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_authFactory.Object); x.AddSingleton(_authFactory.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -53,6 +57,11 @@ namespace Ocelot.UnitTests.Authentication
.Configure(app => .Configure(app =>
{ {
app.UseAuthenticationMiddleware(); app.UseAuthenticationMiddleware();
app.Run(async x =>
{
await x.Response.WriteAsync("The user is authenticated");
});
}); });
_server = new TestServer(builder); _server = new TestServer(builder);
@ -60,28 +69,18 @@ namespace Ocelot.UnitTests.Authentication
} }
[Fact] [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<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().Build()))) this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().Build())))
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenNoExceptionsAreThrown()) .Then(x => x.ThenTheUserIsAuthenticated())
.BDDfy(); .BDDfy();
} }
private void SetUpLogger() private void ThenTheUserIsAuthenticated()
{ {
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>(); var content = _result.Content.ReadAsStringAsync().Result;
content.ShouldBe("The user is authenticated");
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<AuthenticationMiddleware>())
.Returns(logger.Object);
}
private void ThenNoExceptionsAreThrown()
{
//todo not suck
} }
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)

View File

@ -6,9 +6,9 @@ using System.Security.Claims;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Authorisation; using Ocelot.Authorisation;
using Ocelot.Cache.Middleware;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
@ -31,19 +31,18 @@ namespace Ocelot.UnitTests.Authorization
private readonly HttpClient _client; private readonly HttpClient _client;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<DownstreamRoute> _downstreamRoute; private OkResponse<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public AuthorisationMiddlewareTests() public AuthorisationMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_authService = new Mock<IAuthoriser>(); _authService = new Mock<IAuthoriser>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object); x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_authService.Object); x.AddSingleton(_authService.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -62,7 +61,7 @@ namespace Ocelot.UnitTests.Authorization
} }
[Fact] [Fact]
public void happy_path() public void should_call_authorisation_service()
{ {
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithIsAuthorised(true).Build()))) this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithIsAuthorised(true).Build())))
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true))) .And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
@ -71,17 +70,6 @@ namespace Ocelot.UnitTests.Authorization
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<AuthorisationMiddleware>())
.Returns(logger.Object);
}
private void GivenTheAuthServiceReturns(Response<bool> expected) private void GivenTheAuthServiceReturns(Response<bool> expected)
{ {
_authService _authService

View File

@ -6,6 +6,7 @@ using CacheManager.Core;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Cache; using Ocelot.Cache;
using Ocelot.Cache.Middleware; using Ocelot.Cache.Middleware;
@ -25,7 +26,6 @@ namespace Ocelot.UnitTests.Cache
{ {
private readonly Mock<IOcelotCache<HttpResponseMessage>> _cacheManager; private readonly Mock<IOcelotCache<HttpResponseMessage>> _cacheManager;
private readonly Mock<IRequestScopedDataRepository> _scopedRepo; private readonly Mock<IRequestScopedDataRepository> _scopedRepo;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
private readonly string _url; private readonly string _url;
private readonly TestServer _server; private readonly TestServer _server;
private readonly HttpClient _client; private readonly HttpClient _client;
@ -37,14 +37,13 @@ namespace Ocelot.UnitTests.Cache
_cacheManager = new Mock<IOcelotCache<HttpResponseMessage>>(); _cacheManager = new Mock<IOcelotCache<HttpResponseMessage>>();
_scopedRepo = new Mock<IRequestScopedDataRepository>(); _scopedRepo = new Mock<IRequestScopedDataRepository>();
SetUpLogger();
_url = "http://localhost:51879"; _url = "http://localhost:51879";
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging(); x.AddLogging();
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_cacheManager.Object); x.AddSingleton(_cacheManager.Object);
x.AddSingleton(_scopedRepo.Object); x.AddSingleton(_scopedRepo.Object);
}) })
@ -85,16 +84,6 @@ namespace Ocelot.UnitTests.Cache
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<OutputCacheMiddleware>())
.Returns(logger.Object);
}
private void GivenTheDownstreamRouteIs() private void GivenTheDownstreamRouteIs()
{ {

View File

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Cache.Middleware; using Ocelot.Cache.Middleware;
using Ocelot.Claims; using Ocelot.Claims;
@ -31,19 +32,19 @@ namespace Ocelot.UnitTests.Claims
private readonly HttpClient _client; private readonly HttpClient _client;
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public ClaimsBuilderMiddlewareTests() public ClaimsBuilderMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_addHeaders = new Mock<IAddClaimsToRequest>(); _addHeaders = new Mock<IAddClaimsToRequest>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object); x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_addHeaders.Object); x.AddSingleton(_addHeaders.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -62,7 +63,7 @@ namespace Ocelot.UnitTests.Claims
} }
[Fact] [Fact]
public void happy_path() public void should_call_claims_to_request_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
@ -80,17 +81,6 @@ namespace Ocelot.UnitTests.Claims
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<ClaimsBuilderMiddleware>())
.Returns(logger.Object);
}
private void GivenTheAddClaimsToRequestReturns() private void GivenTheAddClaimsToRequestReturns()
{ {
_addHeaders _addHeaders

View File

@ -5,8 +5,8 @@ using System.Net.Http;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Claims.Middleware;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
@ -29,19 +29,18 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private readonly HttpClient _client; private readonly HttpClient _client;
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public DownstreamRouteFinderMiddlewareTests() public DownstreamRouteFinderMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_downstreamRouteFinder = new Mock<IDownstreamRouteFinder>(); _downstreamRouteFinder = new Mock<IDownstreamRouteFinder>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object); x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_downstreamRouteFinder.Object); x.AddSingleton(_downstreamRouteFinder.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -60,7 +59,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
} }
[Fact] [Fact]
public void happy_path() public void should_call_scoped_data_repository_correctly()
{ {
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build()))) this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
@ -68,16 +67,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>())
.Returns(logger.Object);
}
private void ThenTheScopedDataRepositoryIsCalledCorrectly() private void ThenTheScopedDataRepositoryIsCalledCorrectly()
{ {

View File

@ -5,6 +5,7 @@ using System.Net.Http;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
@ -30,19 +31,18 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<DownstreamUrl> _downstreamUrl; private OkResponse<DownstreamUrl> _downstreamUrl;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public DownstreamUrlCreatorMiddlewareTests() public DownstreamUrlCreatorMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlPathPlaceholderReplacer>(); _downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlPathPlaceholderReplacer>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object); x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object); x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -61,7 +61,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
} }
[Fact] [Fact]
public void happy_path() public void should_call_scoped_data_repository_correctly()
{ {
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build()))) this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
.And(x => x.TheUrlReplacerReturns("any old string")) .And(x => x.TheUrlReplacerReturns("any old string"))
@ -70,18 +70,6 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<DownstreamUrlCreatorMiddleware>())
.Returns(logger.Object);
}
private void TheUrlReplacerReturns(string downstreamUrl) private void TheUrlReplacerReturns(string downstreamUrl)
{ {
_downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(downstreamUrl)); _downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(downstreamUrl));

View File

@ -6,14 +6,17 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.DownstreamUrlCreator.Middleware;
using Ocelot.Headers; using Ocelot.Headers;
using Ocelot.Headers.Middleware; using Ocelot.Headers.Middleware;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -35,9 +38,13 @@ namespace Ocelot.UnitTests.Headers
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_addHeaders = new Mock<IAddHeadersToRequest>(); _addHeaders = new Mock<IAddHeadersToRequest>();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_addHeaders.Object); x.AddSingleton(_addHeaders.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -56,7 +63,7 @@ namespace Ocelot.UnitTests.Headers
} }
[Fact] [Fact]
public void happy_path() public void should_call_add_headers_to_request_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
@ -68,13 +75,13 @@ namespace Ocelot.UnitTests.Headers
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheAddHeadersToRequestReturns("123")) .And(x => x.GivenTheAddHeadersToRequestReturns())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly()) .Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
private void GivenTheAddHeadersToRequestReturns(string claimValue) private void GivenTheAddHeadersToRequestReturns()
{ {
_addHeaders _addHeaders
.Setup(x => x.SetHeadersOnContext(It.IsAny<List<ClaimToThing>>(), .Setup(x => x.SetHeadersOnContext(It.IsAny<List<ClaimToThing>>(),

View File

@ -6,12 +6,15 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Headers.Middleware;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.QueryStrings; using Ocelot.QueryStrings;
using Ocelot.QueryStrings.Middleware; using Ocelot.QueryStrings.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
@ -38,6 +41,8 @@ namespace Ocelot.UnitTests.QueryStrings
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_addQueries.Object); x.AddSingleton(_addQueries.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -56,7 +61,7 @@ namespace Ocelot.UnitTests.QueryStrings
} }
[Fact] [Fact]
public void happy_path() public void should_call_add_queries_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
@ -70,7 +75,7 @@ namespace Ocelot.UnitTests.QueryStrings
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheAddHeadersToRequestReturns()) .And(x => x.GivenTheAddHeadersToRequestReturns())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly()) .Then(x => x.ThenTheAddQueriesToRequestIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
@ -82,7 +87,7 @@ namespace Ocelot.UnitTests.QueryStrings
.Returns(new OkResponse()); .Returns(new OkResponse());
} }
private void ThenTheAddHeadersToRequestIsCalledCorrectly() private void ThenTheAddQueriesToRequestIsCalledCorrectly()
{ {
_addQueries _addQueries
.Verify(x => x.SetQueriesOnContext(It.IsAny<List<ClaimToThing>>(), .Verify(x => x.SetQueriesOnContext(It.IsAny<List<ClaimToThing>>(),

View File

@ -7,11 +7,13 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Request.Builder; using Ocelot.Request.Builder;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
@ -37,10 +39,11 @@ namespace Ocelot.UnitTests.Request
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_requestBuilder = new Mock<IRequestCreator>(); _requestBuilder = new Mock<IRequestCreator>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_requestBuilder.Object); x.AddSingleton(_requestBuilder.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -59,7 +62,7 @@ namespace Ocelot.UnitTests.Request
} }
[Fact] [Fact]
public void happy_path() public void should_call_scoped_data_repository_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),

View File

@ -8,11 +8,14 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Request.Middleware;
using Ocelot.RequestId.Middleware; using Ocelot.RequestId.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
using Shouldly; using Shouldly;
@ -36,10 +39,11 @@ namespace Ocelot.UnitTests.RequestId
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
.UseUrls(_url) .UseUrls(_url)

View File

@ -6,8 +6,11 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.QueryStrings.Middleware;
using Ocelot.Requester; using Ocelot.Requester;
using Ocelot.Requester.Middleware; using Ocelot.Requester.Middleware;
using Ocelot.Responder; using Ocelot.Responder;
@ -33,10 +36,11 @@ namespace Ocelot.UnitTests.Requester
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_requester = new Mock<IHttpRequester>(); _requester = new Mock<IHttpRequester>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_requester.Object); x.AddSingleton(_requester.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -55,7 +59,7 @@ namespace Ocelot.UnitTests.Requester
} }
[Fact] [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()))) this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),new CookieContainer())))
.And(x => x.GivenTheRequesterReturns(new HttpResponseMessage())) .And(x => x.GivenTheRequesterReturns(new HttpResponseMessage()))

View File

@ -5,8 +5,10 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responder; using Ocelot.Responder;
using Ocelot.Responder.Middleware; using Ocelot.Responder.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
@ -15,7 +17,7 @@ using Xunit;
namespace Ocelot.UnitTests.Responder namespace Ocelot.UnitTests.Responder
{ {
public class HttpErrorResponderMiddlewareTests : IDisposable public class ResponderMiddlewareTests : IDisposable
{ {
private readonly Mock<IHttpResponder> _responder; private readonly Mock<IHttpResponder> _responder;
private readonly Mock<IRequestScopedDataRepository> _scopedRepository; private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
@ -26,16 +28,17 @@ namespace Ocelot.UnitTests.Responder
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<HttpResponseMessage> _response; private OkResponse<HttpResponseMessage> _response;
public HttpErrorResponderMiddlewareTests() public ResponderMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_responder = new Mock<IHttpResponder>(); _responder = new Mock<IHttpResponder>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_codeMapper = new Mock<IErrorsToHttpStatusCodeMapper>(); _codeMapper = new Mock<IErrorsToHttpStatusCodeMapper>();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_codeMapper.Object); x.AddSingleton(_codeMapper.Object);
x.AddSingleton(_responder.Object); x.AddSingleton(_responder.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
@ -47,7 +50,7 @@ namespace Ocelot.UnitTests.Responder
.UseUrls(_url) .UseUrls(_url)
.Configure(app => .Configure(app =>
{ {
app.UseHttpErrorResponderMiddleware(); app.UseResponderMiddleware();
}); });
_server = new TestServer(builder); _server = new TestServer(builder);
@ -55,7 +58,7 @@ namespace Ocelot.UnitTests.Responder
} }
[Fact] [Fact]
public void happy_path() public void should_not_return_any_errors()
{ {
this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage())) this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage()))
.And(x => x.GivenThereAreNoPipelineErrors()) .And(x => x.GivenThereAreNoPipelineErrors())