mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:42:50 +08:00
Merge branch 'release-5.0.0'
This commit is contained in:
commit
b8c908558e
@ -1,26 +1,16 @@
|
|||||||
Delegating Handers
|
Delegating Handers
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_ and I decided that it was going to be useful in various ways.
|
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_
|
||||||
|
and I decided that it was going to be useful in various ways. Since then we extended it in `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/264>`_.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
In order to add delegating handlers to the HttpClient transport you need to do the following.
|
In order to add delegating handlers to the HttpClient transport you need to do two main things.
|
||||||
|
|
||||||
This will register the Handlers as singletons. Because Ocelot caches the HttpClient for the downstream services to avoid
|
First in order to create a class that can be used a delegating handler it must look as follows. We are going to register these handlers in the
|
||||||
socket exhaustion (well known http client issue) you can only register singleton handlers.
|
asp.net core container so you can inject any other services you have registered into the constructor of your handler.
|
||||||
|
|
||||||
.. code-block:: csharp
|
|
||||||
|
|
||||||
services.AddOcelot()
|
|
||||||
.AddDelegatingHandler<FakeHandler>()
|
|
||||||
.AddDelegatingHandler<FakeHandlerTwo>()
|
|
||||||
|
|
||||||
You can have as many DelegatingHandlers as you want and they are run in a first in first out order. If you are using Ocelot's QoS functionality then that will always be run after your last delegating handler. If you are also registering handlers in DI these will be
|
|
||||||
run first.
|
|
||||||
|
|
||||||
In order to create a class that can be used a delegating handler it must look as follows
|
|
||||||
|
|
||||||
.. code-block:: csharp
|
.. code-block:: csharp
|
||||||
|
|
||||||
@ -33,4 +23,57 @@ In order to create a class that can be used a delegating handler it must look as
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Next you must add the handlers to Ocelot's container either as singleton like follows..
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
services.AddOcelot()
|
||||||
|
.AddSingletonDelegatingHandler<FakeHandler>()
|
||||||
|
.AddSingletonDelegatingHandler<FakeHandlerTwo>()
|
||||||
|
|
||||||
|
Or transient as below...
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
services.AddOcelot()
|
||||||
|
.AddTransientDelegatingHandler<FakeHandler>()
|
||||||
|
.AddTransientDelegatingHandler<FakeHandlerTwo>()
|
||||||
|
|
||||||
|
Both of these Add methods have a default parameter called global which is set to false. If it is false then the intent of
|
||||||
|
the DelegatingHandler is to be applied to specific ReRoutes via configuration.json (more on that later). If it is set to true
|
||||||
|
then it becomes a global handler and will be applied to all ReRoutes.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
services.AddOcelot()
|
||||||
|
.AddSingletonDelegatingHandler<FakeHandler>(true)
|
||||||
|
|
||||||
|
Or transient as below...
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
services.AddOcelot()
|
||||||
|
.AddTransientDelegatingHandler<FakeHandler>(true)
|
||||||
|
|
||||||
|
Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers
|
||||||
|
then you must add the following json to the specific ReRoute in configuration.json. The names in the array must match the class names of your
|
||||||
|
DelegatingHandlers for Ocelot to match them together.
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
"DelegatingHandlers": [
|
||||||
|
"FakeHandlerTwo",
|
||||||
|
"FakeHandler"
|
||||||
|
]
|
||||||
|
|
||||||
|
You can have as many DelegatingHandlers as you want and they are run in the following order:
|
||||||
|
|
||||||
|
1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from configuration.json.
|
||||||
|
2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from configuration.json ordered as they are in the DelegatingHandlers array.
|
||||||
|
3. Tracing DelegatingHandler if enabled (see tracing docs).
|
||||||
|
4. QoS DelegatingHandler if enabled (see QoS docs).
|
||||||
|
5. The HttpClient sends the HttpRequestMessage.
|
||||||
|
|
||||||
Hopefully other people will find this feature useful!
|
Hopefully other people will find this feature useful!
|
@ -1,8 +0,0 @@
|
|||||||
namespace Ocelot.Authentication.Handler
|
|
||||||
{
|
|
||||||
public enum SupportedAuthenticationProviders
|
|
||||||
{
|
|
||||||
IdentityServer,
|
|
||||||
Jwt
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,3 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Ocelot.Middleware.Pipeline;
|
using Ocelot.Middleware.Pipeline;
|
||||||
|
|
||||||
namespace Ocelot.Authentication.Middleware
|
namespace Ocelot.Authentication.Middleware
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
using Ocelot.Infrastructure.RequestData;
|
namespace Ocelot.Authorisation.Middleware
|
||||||
using Ocelot.Logging;
|
|
||||||
using Ocelot.Responses;
|
|
||||||
using Ocelot.Configuration;
|
|
||||||
|
|
||||||
namespace Ocelot.Authorisation.Middleware
|
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Errors;
|
using Errors;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
|
using Logging;
|
||||||
|
using Responses;
|
||||||
|
using Configuration;
|
||||||
|
|
||||||
public class AuthorisationMiddleware : OcelotMiddleware
|
public class AuthorisationMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
|
@ -2,8 +2,6 @@ using Ocelot.Middleware.Pipeline;
|
|||||||
|
|
||||||
namespace Ocelot.Authorisation.Middleware
|
namespace Ocelot.Authorisation.Middleware
|
||||||
{
|
{
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
|
|
||||||
public static class AuthorisationMiddlewareMiddlewareExtensions
|
public static class AuthorisationMiddlewareMiddlewareExtensions
|
||||||
{
|
{
|
||||||
public static IOcelotPipelineBuilder UseAuthorisationMiddleware(this IOcelotPipelineBuilder builder)
|
public static IOcelotPipelineBuilder UseAuthorisationMiddleware(this IOcelotPipelineBuilder builder)
|
||||||
|
@ -34,9 +34,9 @@ namespace Ocelot.Authorisation
|
|||||||
|
|
||||||
var userScopes = values.Data;
|
var userScopes = values.Data;
|
||||||
|
|
||||||
List<string> matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
|
var matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
|
||||||
|
|
||||||
if (matchesScopes == null || matchesScopes.Count == 0)
|
if (matchesScopes.Count == 0)
|
||||||
{
|
{
|
||||||
return new ErrorResponse<bool>(new List<Error>
|
return new ErrorResponse<bool>(new List<Error>
|
||||||
{
|
{
|
||||||
|
@ -36,9 +36,12 @@ namespace Ocelot.Configuration.Builder
|
|||||||
private readonly List<DownstreamHostAndPort> _downstreamAddresses;
|
private readonly List<DownstreamHostAndPort> _downstreamAddresses;
|
||||||
private string _upstreamHost;
|
private string _upstreamHost;
|
||||||
private string _key;
|
private string _key;
|
||||||
|
private List<string> _delegatingHandlers;
|
||||||
|
|
||||||
public DownstreamReRouteBuilder()
|
public DownstreamReRouteBuilder()
|
||||||
{
|
{
|
||||||
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
||||||
|
_delegatingHandlers = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
||||||
@ -215,6 +218,12 @@ namespace Ocelot.Configuration.Builder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DownstreamReRouteBuilder WithDelegatingHandlers(List<string> delegatingHandlers)
|
||||||
|
{
|
||||||
|
_delegatingHandlers = delegatingHandlers;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DownstreamReRoute Build()
|
public DownstreamReRoute Build()
|
||||||
{
|
{
|
||||||
return new DownstreamReRoute(
|
return new DownstreamReRoute(
|
||||||
@ -243,7 +252,8 @@ namespace Ocelot.Configuration.Builder
|
|||||||
_isAuthorised,
|
_isAuthorised,
|
||||||
_authenticationOptions,
|
_authenticationOptions,
|
||||||
new PathTemplate(_downstreamPathTemplate),
|
new PathTemplate(_downstreamPathTemplate),
|
||||||
_reRouteKey);
|
_reRouteKey,
|
||||||
|
_delegatingHandlers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
|
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
|
||||||
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
|
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
|
||||||
.WithUpstreamHost(fileReRoute.UpstreamHost)
|
.WithUpstreamHost(fileReRoute.UpstreamHost)
|
||||||
|
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return reRoute;
|
return reRoute;
|
||||||
|
@ -31,8 +31,10 @@ namespace Ocelot.Configuration
|
|||||||
bool isAuthorised,
|
bool isAuthorised,
|
||||||
AuthenticationOptions authenticationOptions,
|
AuthenticationOptions authenticationOptions,
|
||||||
PathTemplate downstreamPathTemplate,
|
PathTemplate downstreamPathTemplate,
|
||||||
string reRouteKey)
|
string reRouteKey,
|
||||||
|
List<string> delegatingHandlers)
|
||||||
{
|
{
|
||||||
|
DelegatingHandlers = delegatingHandlers;
|
||||||
Key = key;
|
Key = key;
|
||||||
UpstreamPathTemplate = upstreamPathTemplate;
|
UpstreamPathTemplate = upstreamPathTemplate;
|
||||||
UpstreamHeadersFindAndReplace = upstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
UpstreamHeadersFindAndReplace = upstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
||||||
@ -87,5 +89,6 @@ namespace Ocelot.Configuration
|
|||||||
public AuthenticationOptions AuthenticationOptions { get; private set; }
|
public AuthenticationOptions AuthenticationOptions { get; private set; }
|
||||||
public PathTemplate DownstreamPathTemplate { get; private set; }
|
public PathTemplate DownstreamPathTemplate { get; private set; }
|
||||||
public string ReRouteKey { get; private set; }
|
public string ReRouteKey { get; private set; }
|
||||||
|
public List<string> DelegatingHandlers {get;private set;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ namespace Ocelot.Configuration.File
|
|||||||
HttpHandlerOptions = new FileHttpHandlerOptions();
|
HttpHandlerOptions = new FileHttpHandlerOptions();
|
||||||
UpstreamHeaderTransform = new Dictionary<string, string>();
|
UpstreamHeaderTransform = new Dictionary<string, string>();
|
||||||
DownstreamHostAndPorts = new List<FileHostAndPort>();
|
DownstreamHostAndPorts = new List<FileHostAndPort>();
|
||||||
|
DelegatingHandlers = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DownstreamPathTemplate { get; set; }
|
public string DownstreamPathTemplate { get; set; }
|
||||||
@ -44,5 +45,6 @@ namespace Ocelot.Configuration.File
|
|||||||
public List<FileHostAndPort> DownstreamHostAndPorts {get;set;}
|
public List<FileHostAndPort> DownstreamHostAndPorts {get;set;}
|
||||||
public string UpstreamHost { get; set; }
|
public string UpstreamHost { get; set; }
|
||||||
public string Key { get;set; }
|
public string Key { get;set; }
|
||||||
|
public List<string> DelegatingHandlers {get;set;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ using CacheManager.Core;
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using Ocelot.Requester;
|
|
||||||
|
|
||||||
namespace Ocelot.DependencyInjection
|
namespace Ocelot.DependencyInjection
|
||||||
{
|
{
|
||||||
@ -19,6 +18,10 @@ namespace Ocelot.DependencyInjection
|
|||||||
|
|
||||||
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
||||||
|
|
||||||
IOcelotBuilder AddDelegatingHandler<T>() where T : DelegatingHandler;
|
IOcelotBuilder AddSingletonDelegatingHandler<T>(bool global = false)
|
||||||
|
where T : DelegatingHandler;
|
||||||
|
|
||||||
|
IOcelotBuilder AddTransientDelegatingHandler<T>(bool global = false)
|
||||||
|
where T : DelegatingHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,10 +182,41 @@ namespace Ocelot.DependencyInjection
|
|||||||
return new OcelotAdministrationBuilder(_services, _configurationRoot);
|
return new OcelotAdministrationBuilder(_services, _configurationRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IOcelotBuilder AddDelegatingHandler<THandler>()
|
public IOcelotBuilder AddSingletonDelegatingHandler<THandler>(bool global = false)
|
||||||
where THandler : DelegatingHandler
|
where THandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
_services.AddSingleton<DelegatingHandler, THandler>();
|
if(global)
|
||||||
|
{
|
||||||
|
_services.AddSingleton<THandler>();
|
||||||
|
_services.AddSingleton<GlobalDelegatingHandler>(s => {
|
||||||
|
var service = s.GetService<THandler>();
|
||||||
|
return new GlobalDelegatingHandler(service);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_services.AddSingleton<DelegatingHandler, THandler>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOcelotBuilder AddTransientDelegatingHandler<THandler>(bool global = false)
|
||||||
|
where THandler : DelegatingHandler
|
||||||
|
{
|
||||||
|
if(global)
|
||||||
|
{
|
||||||
|
_services.AddTransient<THandler>();
|
||||||
|
_services.AddTransient<GlobalDelegatingHandler>(s => {
|
||||||
|
var service = s.GetService<THandler>();
|
||||||
|
return new GlobalDelegatingHandler(service);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_services.AddTransient<DelegatingHandler, THandler>();
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Ocelot.Authentication
|
namespace Ocelot.Raft
|
||||||
{
|
{
|
||||||
class BearerToken
|
[ExcludeFromCoverage]
|
||||||
|
internal class BearerToken
|
||||||
{
|
{
|
||||||
[JsonProperty("access_token")]
|
[JsonProperty("access_token")]
|
||||||
public string AccessToken { get; set; }
|
public string AccessToken { get; set; }
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
@ -29,13 +30,36 @@ namespace Ocelot.Requester
|
|||||||
|
|
||||||
public Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request)
|
public Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request)
|
||||||
{
|
{
|
||||||
var handlersAppliedToAll = _serviceProvider.GetServices<DelegatingHandler>();
|
var globalDelegatingHandlers = _serviceProvider
|
||||||
|
.GetServices<GlobalDelegatingHandler>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var reRouteSpecificHandlers = _serviceProvider
|
||||||
|
.GetServices<DelegatingHandler>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var handlers = new List<Func<DelegatingHandler>>();
|
var handlers = new List<Func<DelegatingHandler>>();
|
||||||
|
|
||||||
foreach (var handler in handlersAppliedToAll)
|
foreach (var handler in globalDelegatingHandlers)
|
||||||
{
|
{
|
||||||
handlers.Add(() => handler);
|
if (GlobalIsInHandlersConfig(request, handler))
|
||||||
|
{
|
||||||
|
reRouteSpecificHandlers.Add(handler.DelegatingHandler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handlers.Add(() => handler.DelegatingHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.DelegatingHandlers.Any())
|
||||||
|
{
|
||||||
|
var sorted = SortByConfigOrder(request, reRouteSpecificHandlers);
|
||||||
|
|
||||||
|
foreach (var handler in sorted)
|
||||||
|
{
|
||||||
|
handlers.Add(() => handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.HttpHandlerOptions.UseTracing)
|
if (request.HttpHandlerOptions.UseTracing)
|
||||||
@ -57,5 +81,22 @@ namespace Ocelot.Requester
|
|||||||
|
|
||||||
return new OkResponse<List<Func<DelegatingHandler>>>(handlers);
|
return new OkResponse<List<Func<DelegatingHandler>>>(handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<DelegatingHandler> SortByConfigOrder(DownstreamReRoute request, List<DelegatingHandler> reRouteSpecificHandlers)
|
||||||
|
{
|
||||||
|
return reRouteSpecificHandlers
|
||||||
|
.Where(x => request.DelegatingHandlers.Contains(x.GetType().Name))
|
||||||
|
.OrderBy(d =>
|
||||||
|
{
|
||||||
|
var type = d.GetType().Name;
|
||||||
|
var pos = request.DelegatingHandlers.IndexOf(type);
|
||||||
|
return pos;
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GlobalIsInHandlersConfig(DownstreamReRoute request, GlobalDelegatingHandler handler)
|
||||||
|
{
|
||||||
|
return request.DelegatingHandlers.Contains(handler.DelegatingHandler.GetType().Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,4 +76,19 @@ namespace Ocelot.Requester
|
|||||||
return baseUrl;
|
return baseUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ReRouteDelegatingHandler<T> where T : DelegatingHandler
|
||||||
|
{
|
||||||
|
public T DelegatingHandler { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GlobalDelegatingHandler
|
||||||
|
{
|
||||||
|
public GlobalDelegatingHandler(DelegatingHandler delegatingHandler)
|
||||||
|
{
|
||||||
|
DelegatingHandler = delegatingHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelegatingHandler DelegatingHandler { get; private set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
_builder.Start();
|
_builder.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_builder?.Dispose();
|
_builder?.Dispose();
|
||||||
|
@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using Shouldly;
|
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
@ -26,9 +26,48 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_steps = new Steps();
|
_steps = new Steps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_call_re_route_ordered_specific_handlers()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 7197,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
DelegatingHandlers = new List<string>
|
||||||
|
{
|
||||||
|
"FakeHandlerTwo",
|
||||||
|
"FakeHandler"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7197", "/", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunningWithSpecficHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
|
.And(x => ThenTheOrderedHandlersAreCalledCorrectly())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_di_handlers()
|
public void should_call_global_di_handlers()
|
||||||
{
|
{
|
||||||
var configuration = new FileConfiguration
|
var configuration = new FileConfiguration
|
||||||
{
|
{
|
||||||
@ -54,7 +93,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7187", "/", 200, "Hello from Laura"))
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7187", "/", 200, "Hello from Laura"))
|
||||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
.And(x => _steps.GivenOcelotIsRunningWithHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
|
.And(x => _steps.GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
|
||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
@ -62,9 +101,8 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_di_handlers_with_dependency()
|
public void should_call_global_di_handlers_with_dependency()
|
||||||
{
|
{
|
||||||
var configuration = new FileConfiguration
|
var configuration = new FileConfiguration
|
||||||
{
|
{
|
||||||
@ -92,7 +130,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7188", "/", 200, "Hello from Laura"))
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7188", "/", 200, "Hello from Laura"))
|
||||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
.And(x => _steps.GivenOcelotIsRunningWithHandlersRegisteredInDi<FakeHandlerWithDependency>(dependency))
|
.And(x => _steps.GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<FakeHandlerWithDependency>(dependency))
|
||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
@ -110,45 +148,54 @@ namespace Ocelot.AcceptanceTests
|
|||||||
FakeHandler.TimeCalled.ShouldBeLessThan(FakeHandlerTwo.TimeCalled);
|
FakeHandler.TimeCalled.ShouldBeLessThan(FakeHandlerTwo.TimeCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheOrderedHandlersAreCalledCorrectly()
|
||||||
|
{
|
||||||
|
FakeHandlerTwo.TimeCalled.ShouldBeLessThan(FakeHandler.TimeCalled);
|
||||||
|
}
|
||||||
|
|
||||||
public class FakeDependency
|
public class FakeDependency
|
||||||
{
|
{
|
||||||
public bool Called;
|
public bool Called;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeHandlerWithDependency : DelegatingHandler
|
// ReSharper disable once ClassNeverInstantiated.Local
|
||||||
|
private class FakeHandlerWithDependency : DelegatingHandler
|
||||||
{
|
{
|
||||||
private FakeDependency _dependency;
|
private readonly FakeDependency _dependency;
|
||||||
|
|
||||||
public FakeHandlerWithDependency(FakeDependency dependency)
|
public FakeHandlerWithDependency(FakeDependency dependency)
|
||||||
{
|
{
|
||||||
_dependency = dependency;
|
_dependency = dependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_dependency.Called = true;
|
_dependency.Called = true;
|
||||||
return await base.SendAsync(request, cancellationToken);
|
return base.SendAsync(request, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeHandler : DelegatingHandler
|
// ReSharper disable once ClassNeverInstantiated.Local
|
||||||
|
private class FakeHandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
public static DateTime TimeCalled { get; private set; }
|
public static DateTime TimeCalled { get; private set; }
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
TimeCalled = DateTime.Now;
|
TimeCalled = DateTime.Now;
|
||||||
return await base.SendAsync(request, cancellationToken);
|
return base.SendAsync(request, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class FakeHandlerTwo : DelegatingHandler
|
|
||||||
|
// ReSharper disable once ClassNeverInstantiated.Local
|
||||||
|
private class FakeHandlerTwo : DelegatingHandler
|
||||||
{
|
{
|
||||||
public static DateTime TimeCalled { get; private set; }
|
public static DateTime TimeCalled { get; private set; }
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
TimeCalled = DateTime.Now;
|
TimeCalled = DateTime.Now;
|
||||||
return await base.SendAsync(request, cancellationToken);
|
return base.SendAsync(request, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,4 +50,9 @@
|
|||||||
<PackageReference Include="xunit" Version="2.3.1" />
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Castle.Core">
|
||||||
|
<HintPath>..\..\..\..\Users\TGP\.nuget\packages\castle.core\4.2.1\lib\netstandard1.3\Castle.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -25,6 +25,7 @@ using Ocelot.AcceptanceTests.Caching;
|
|||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
|
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
|
||||||
|
using Ocelot.Requester;
|
||||||
|
|
||||||
namespace Ocelot.AcceptanceTests
|
namespace Ocelot.AcceptanceTests
|
||||||
{
|
{
|
||||||
@ -175,7 +176,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_ocelotClient = _ocelotServer.CreateClient();
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne, TWo>()
|
public void GivenOcelotIsRunningWithSpecficHandlersRegisteredInDi<TOne, TWo>()
|
||||||
where TOne : DelegatingHandler
|
where TOne : DelegatingHandler
|
||||||
where TWo : DelegatingHandler
|
where TWo : DelegatingHandler
|
||||||
{
|
{
|
||||||
@ -195,8 +196,8 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
s.AddSingleton(_webHostBuilder);
|
s.AddSingleton(_webHostBuilder);
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddDelegatingHandler<TOne>()
|
.AddSingletonDelegatingHandler<TOne>()
|
||||||
.AddDelegatingHandler<TWo>();
|
.AddSingletonDelegatingHandler<TWo>();
|
||||||
})
|
})
|
||||||
.Configure(a =>
|
.Configure(a =>
|
||||||
{
|
{
|
||||||
@ -208,7 +209,40 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_ocelotClient = _ocelotServer.CreateClient();
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne>(FakeDependency dependency)
|
public void GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<TOne, TWo>()
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
where TWo : DelegatingHandler
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddSingleton(_webHostBuilder);
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddSingletonDelegatingHandler<TOne>(true)
|
||||||
|
.AddSingletonDelegatingHandler<TWo>(true);
|
||||||
|
})
|
||||||
|
.Configure(a =>
|
||||||
|
{
|
||||||
|
a.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningWithGlobalHandlersRegisteredInDi<TOne>(FakeDependency dependency)
|
||||||
where TOne : DelegatingHandler
|
where TOne : DelegatingHandler
|
||||||
{
|
{
|
||||||
_webHostBuilder = new WebHostBuilder();
|
_webHostBuilder = new WebHostBuilder();
|
||||||
@ -228,7 +262,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
s.AddSingleton(_webHostBuilder);
|
s.AddSingleton(_webHostBuilder);
|
||||||
s.AddSingleton<FakeDependency>(dependency);
|
s.AddSingleton<FakeDependency>(dependency);
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddDelegatingHandler<TOne>();
|
.AddSingletonDelegatingHandler<TOne>(true);
|
||||||
})
|
})
|
||||||
.Configure(a =>
|
.Configure(a =>
|
||||||
{
|
{
|
||||||
@ -618,15 +652,16 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
public void GivenThePostHasGzipContent(object input)
|
public void GivenThePostHasGzipContent(object input)
|
||||||
{
|
{
|
||||||
string json = JsonConvert.SerializeObject(input);
|
var json = JsonConvert.SerializeObject(input);
|
||||||
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
|
var jsonBytes = Encoding.UTF8.GetBytes(json);
|
||||||
MemoryStream ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
|
using (var gzip = new GZipStream(ms, CompressionMode.Compress, true))
|
||||||
{
|
{
|
||||||
gzip.Write(jsonBytes, 0, jsonBytes.Length);
|
gzip.Write(jsonBytes, 0, jsonBytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
StreamContent content = new StreamContent(ms);
|
var content = new StreamContent(ms);
|
||||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||||
content.Headers.ContentEncoding.Add("gzip");
|
content.Headers.ContentEncoding.Add("gzip");
|
||||||
_postContent = content;
|
_postContent = content;
|
||||||
|
@ -402,11 +402,14 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
var handlers = new List<string> {"Polly", "Tracer"};
|
||||||
|
|
||||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamScheme("https")
|
.WithDownstreamScheme("https")
|
||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
|
.WithDelegatingHandlers(handlers)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -419,6 +422,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
UpstreamPathTemplate = "/api/products/{productId}",
|
UpstreamPathTemplate = "/api/products/{productId}",
|
||||||
DownstreamPathTemplate = "/products/{productId}",
|
DownstreamPathTemplate = "/products/{productId}",
|
||||||
UpstreamHttpMethod = new List<string> { "Get" },
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
DelegatingHandlers = handlers
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
@ -822,6 +826,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
result.DownstreamReRoute[0].ClaimsToHeaders.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToHeaders.Count);
|
result.DownstreamReRoute[0].ClaimsToHeaders.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToHeaders.Count);
|
||||||
result.DownstreamReRoute[0].ClaimsToQueries.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToQueries.Count);
|
result.DownstreamReRoute[0].ClaimsToQueries.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToQueries.Count);
|
||||||
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
|
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
|
||||||
|
result.DownstreamReRoute[0].DelegatingHandlers.ShouldBe(expected.DownstreamReRoute[0].DelegatingHandlers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,26 +28,58 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
private readonly IConfiguration _configRoot;
|
private readonly IConfiguration _configRoot;
|
||||||
private IOcelotBuilder _ocelotBuilder;
|
private IOcelotBuilder _ocelotBuilder;
|
||||||
private readonly int _maxRetries;
|
private readonly int _maxRetries;
|
||||||
|
private Exception _ex;
|
||||||
|
|
||||||
public OcelotBuilderTests()
|
public OcelotBuilderTests()
|
||||||
{
|
{
|
||||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||||
_services = new ServiceCollection();
|
_services = new ServiceCollection();
|
||||||
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
|
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
|
||||||
_services.AddSingleton<IConfiguration>(_configRoot);
|
_services.AddSingleton(_configRoot);
|
||||||
_maxRetries = 100;
|
_maxRetries = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Exception _ex;
|
[Fact]
|
||||||
|
public void should_add_specific_delegating_handlers_transient()
|
||||||
|
{
|
||||||
|
this.Given(x => WhenISetUpOcelotServices())
|
||||||
|
.When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
|
||||||
|
.And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||||
|
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.And(x => ThenTheSpecificHandlersAreTransient())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_add_delegating_handlers_with_di()
|
public void should_add_specific_delegating_handler_singleton()
|
||||||
{
|
{
|
||||||
|
|
||||||
this.Given(x => WhenISetUpOcelotServices())
|
this.Given(x => WhenISetUpOcelotServices())
|
||||||
.When(x => AddDelegate<FakeDelegatingHandler>())
|
.When(x => AddSpecificDelegatingHandler<FakeDelegatingHandler>())
|
||||||
.And(x => AddDelegate<FakeDelegatingHandlerTwo>())
|
.And(x => AddSpecificDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||||
|
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.And(x => ThenTheSpecificHandlersAreSingleton())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_add_global_delegating_handlers_transient()
|
||||||
|
{
|
||||||
|
this.Given(x => WhenISetUpOcelotServices())
|
||||||
|
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||||
|
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.And(x => ThenTheGlobalHandlersAreTransient())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_add_global_delegating_handlers_singleton()
|
||||||
|
{
|
||||||
|
this.Given(x => WhenISetUpOcelotServices())
|
||||||
|
.When(x => AddGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||||
|
.And(x => AddGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||||
|
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.And(x => ThenTheGlobalHandlersAreSingleton())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,16 +150,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenISetUpAdministration()
|
|
||||||
{
|
|
||||||
_ocelotBuilder.AddAdministration("/administration", "secret");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
|
|
||||||
{
|
|
||||||
_ocelotBuilder.AddAdministration("/administration", options);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_use_logger_factory()
|
public void should_use_logger_factory()
|
||||||
{
|
{
|
||||||
@ -155,6 +177,62 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheSpecificHandlersAreSingleton()
|
||||||
|
{
|
||||||
|
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||||
|
var first = handlers[0];
|
||||||
|
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||||
|
var second = handlers[0];
|
||||||
|
first.ShouldBe(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheSpecificHandlersAreTransient()
|
||||||
|
{
|
||||||
|
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||||
|
var first = handlers[0];
|
||||||
|
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||||
|
var second = handlers[0];
|
||||||
|
first.ShouldNotBe(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheGlobalHandlersAreSingleton()
|
||||||
|
{
|
||||||
|
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||||
|
var first = handlers[0].DelegatingHandler;
|
||||||
|
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||||
|
var second = handlers[0].DelegatingHandler;
|
||||||
|
first.ShouldBe(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheGlobalHandlersAreTransient()
|
||||||
|
{
|
||||||
|
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||||
|
var first = handlers[0].DelegatingHandler;
|
||||||
|
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||||
|
var second = handlers[0].DelegatingHandler;
|
||||||
|
first.ShouldNotBe(second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenISetUpAdministration()
|
||||||
|
{
|
||||||
|
_ocelotBuilder.AddAdministration("/administration", "secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
|
||||||
|
{
|
||||||
|
_ocelotBuilder.AddAdministration("/administration", options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddTransientGlobalDelegatingHandler<T>() where T : DelegatingHandler
|
||||||
|
{
|
||||||
|
_ocelotBuilder.AddTransientDelegatingHandler<T>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddSpecificTransientDelegatingHandler<T>() where T : DelegatingHandler
|
||||||
|
{
|
||||||
|
_ocelotBuilder.AddTransientDelegatingHandler<T>();
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheCorrectAdminPathIsRegitered()
|
private void ThenTheCorrectAdminPathIsRegitered()
|
||||||
{
|
{
|
||||||
_serviceProvider = _services.BuildServiceProvider();
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
@ -163,6 +241,14 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
|
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
|
||||||
|
{
|
||||||
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
|
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||||
|
handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
|
||||||
|
handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
|
||||||
{
|
{
|
||||||
_serviceProvider = _services.BuildServiceProvider();
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||||
@ -174,14 +260,18 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
{
|
{
|
||||||
var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
|
var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
|
||||||
var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
|
var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
|
||||||
var thing = (CacheManager.Core.ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
|
var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
|
||||||
thing.Configuration.MaxRetries.ShouldBe(_maxRetries);
|
|
||||||
|
|
||||||
var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IOcelotConfiguration>));
|
var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IOcelotConfiguration>));
|
||||||
var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IOcelotConfiguration>));
|
var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IOcelotConfiguration>));
|
||||||
|
|
||||||
var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
|
var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
|
||||||
var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));
|
var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));
|
||||||
|
|
||||||
|
instance.Configuration.MaxRetries.ShouldBe(_maxRetries);
|
||||||
|
outputCache.ShouldNotBeNull();
|
||||||
|
ocelotConfigCache.ShouldNotBeNull();
|
||||||
|
ocelotConfigCacheManager.ShouldNotBeNull();
|
||||||
|
fileConfigCache.ShouldNotBeNull();
|
||||||
|
fileConfigCacheManager.ShouldNotBeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenISetUpConsul()
|
private void WhenISetUpConsul()
|
||||||
@ -208,9 +298,14 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddDelegate<T>() where T : DelegatingHandler
|
private void AddGlobalDelegatingHandler<T>() where T : DelegatingHandler
|
||||||
{
|
{
|
||||||
_ocelotBuilder.AddDelegatingHandler<T>();
|
_ocelotBuilder.AddSingletonDelegatingHandler<T>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddSpecificDelegatingHandler<T>() where T : DelegatingHandler
|
||||||
|
{
|
||||||
|
_ocelotBuilder.AddSingletonDelegatingHandler<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAnOcelotBuilderIsReturned()
|
private void ThenAnOcelotBuilderIsReturned()
|
||||||
@ -281,6 +376,7 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
{
|
{
|
||||||
_serviceProvider = _services.BuildServiceProvider();
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
|
var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
|
||||||
|
logger.ShouldNotBeNull();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -293,6 +389,7 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tracingHandler = _serviceProvider.GetService<OcelotHttpTracingHandler>();
|
var tracingHandler = _serviceProvider.GetService<OcelotHttpTracingHandler>();
|
||||||
|
tracingHandler.ShouldNotBeNull();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -19,18 +19,179 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
public class DelegatingHandlerHandlerProviderFactoryTests
|
public class DelegatingHandlerHandlerProviderFactoryTests
|
||||||
{
|
{
|
||||||
private DelegatingHandlerHandlerFactory _factory;
|
private DelegatingHandlerHandlerFactory _factory;
|
||||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||||
private DownstreamReRoute _request;
|
private DownstreamReRoute _request;
|
||||||
private Response<List<Func<DelegatingHandler>>> _provider;
|
private Response<List<Func<DelegatingHandler>>> _result;
|
||||||
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
||||||
private readonly Mock<ITracingHandlerFactory> _tracingFactory;
|
private readonly Mock<ITracingHandlerFactory> _tracingFactory;
|
||||||
private IServiceProvider _serviceProvider;
|
private IServiceProvider _serviceProvider;
|
||||||
|
private readonly IServiceCollection _services;
|
||||||
|
|
||||||
public DelegatingHandlerHandlerProviderFactoryTests()
|
public DelegatingHandlerHandlerProviderFactoryTests()
|
||||||
{
|
{
|
||||||
_tracingFactory = new Mock<ITracingHandlerFactory>();
|
_tracingFactory = new Mock<ITracingHandlerFactory>();
|
||||||
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
|
_services = new ServiceCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_follow_ordering_add_specifics()
|
||||||
|
{
|
||||||
|
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
|
.WithDelegatingHandlers(new List<string>
|
||||||
|
{
|
||||||
|
"FakeDelegatingHandler",
|
||||||
|
"FakeDelegatingHandlerTwo"
|
||||||
|
})
|
||||||
|
.WithReRouteKey("")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
|
.And(x => GivenTheTracingFactoryReturns())
|
||||||
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
|
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerThree, FakeDelegatingHandlerFour>())
|
||||||
|
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.When(x => WhenIGet())
|
||||||
|
.Then(x => ThenThereIsDelegatesInProvider(6))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(1))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(2))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(3))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(4))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(5))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_follow_ordering_order_specifics_and_globals()
|
||||||
|
{
|
||||||
|
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
|
.WithDelegatingHandlers(new List<string>
|
||||||
|
{
|
||||||
|
"FakeDelegatingHandlerTwo",
|
||||||
|
"FakeDelegatingHandler",
|
||||||
|
"FakeDelegatingHandlerFour"
|
||||||
|
})
|
||||||
|
.WithReRouteKey("")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
|
.And(x => GivenTheTracingFactoryReturns())
|
||||||
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
|
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerFour, FakeDelegatingHandlerThree>())
|
||||||
|
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.When(x => WhenIGet())
|
||||||
|
.Then(x => ThenThereIsDelegatesInProvider(6))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0)) //first because global not in config
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(1)) //first from config
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(2)) //second from config
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(3)) //third from config (global)
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(4))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(5))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_follow_ordering_order_specifics()
|
||||||
|
{
|
||||||
|
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
|
.WithDelegatingHandlers(new List<string>
|
||||||
|
{
|
||||||
|
"FakeDelegatingHandlerTwo",
|
||||||
|
"FakeDelegatingHandler"
|
||||||
|
})
|
||||||
|
.WithReRouteKey("")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
|
.And(x => GivenTheTracingFactoryReturns())
|
||||||
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
|
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerThree, FakeDelegatingHandlerFour>())
|
||||||
|
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.When(x => WhenIGet())
|
||||||
|
.Then(x => ThenThereIsDelegatesInProvider(6))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(1))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(2))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(3))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(4))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(5))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_follow_ordering_order_and_only_add_specifics_in_config()
|
||||||
|
{
|
||||||
|
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
|
.WithDelegatingHandlers(new List<string>
|
||||||
|
{
|
||||||
|
"FakeDelegatingHandler",
|
||||||
|
})
|
||||||
|
.WithReRouteKey("")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
|
.And(x => GivenTheTracingFactoryReturns())
|
||||||
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
|
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandlerThree, FakeDelegatingHandlerFour>())
|
||||||
|
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.When(x => WhenIGet())
|
||||||
|
.Then(x => ThenThereIsDelegatesInProvider(5))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerThree>(0))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerFour>(1))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(2))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(3))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(4))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_follow_ordering_dont_add_specifics()
|
||||||
|
{
|
||||||
|
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
|
.WithReRouteKey("")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
|
.And(x => GivenTheTracingFactoryReturns())
|
||||||
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
|
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.When(x => WhenIGet())
|
||||||
|
.Then(x => ThenThereIsDelegatesInProvider(4))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandler>(0))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeDelegatingHandlerTwo>(1))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<FakeTracingHandler>(2))
|
||||||
|
.And(x => ThenHandlerAtPositionIs<PollyCircuitBreakingDelegatingHandler>(3))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_apply_re_route_specific()
|
||||||
|
{
|
||||||
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false))
|
||||||
|
.WithDelegatingHandlers(new List<string>
|
||||||
|
{
|
||||||
|
"FakeDelegatingHandler",
|
||||||
|
"FakeDelegatingHandlerTwo"
|
||||||
|
})
|
||||||
|
.WithReRouteKey("")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
|
.And(x => GivenTheServiceProviderReturnsSpecificDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
|
.When(x => WhenIGet())
|
||||||
|
.Then(x => ThenThereIsDelegatesInProvider(2))
|
||||||
|
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
||||||
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -41,7 +202,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
.And(x => GivenTheServiceProviderReturns<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
.And(x => GivenTheServiceProviderReturnsGlobalDelegatingHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
.When(x => WhenIGet())
|
.When(x => WhenIGet())
|
||||||
.Then(x => ThenThereIsDelegatesInProvider(3))
|
.Then(x => ThenThereIsDelegatesInProvider(3))
|
||||||
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
||||||
@ -91,30 +252,58 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheServiceProviderReturns<TOne, TTwo>()
|
private void ThenHandlerAtPositionIs<T>(int pos)
|
||||||
|
where T : DelegatingHandler
|
||||||
|
{
|
||||||
|
var delegates = _result.Data;
|
||||||
|
var del = delegates[pos].Invoke();
|
||||||
|
del.ShouldBeOfType<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheTracingFactoryReturns()
|
||||||
|
{
|
||||||
|
_tracingFactory
|
||||||
|
.Setup(x => x.Get())
|
||||||
|
.Returns(new FakeTracingHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheServiceProviderReturnsGlobalDelegatingHandlers<TOne, TTwo>()
|
||||||
where TOne : DelegatingHandler
|
where TOne : DelegatingHandler
|
||||||
where TTwo : DelegatingHandler
|
where TTwo : DelegatingHandler
|
||||||
{
|
{
|
||||||
IServiceCollection services = new ServiceCollection();
|
_services.AddTransient<TOne>();
|
||||||
services.AddSingleton<DelegatingHandler, TOne>();
|
_services.AddTransient<GlobalDelegatingHandler>(s => {
|
||||||
services.AddSingleton<DelegatingHandler, TTwo>();
|
var service = s.GetService<TOne>();
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
return new GlobalDelegatingHandler(service);
|
||||||
|
});
|
||||||
|
_services.AddTransient<TTwo>();
|
||||||
|
_services.AddTransient<GlobalDelegatingHandler>(s => {
|
||||||
|
var service = s.GetService<TTwo>();
|
||||||
|
return new GlobalDelegatingHandler(service);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheServiceProviderReturnsNothing()
|
private void GivenTheServiceProviderReturnsSpecificDelegatingHandlers<TOne, TTwo>()
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
where TTwo : DelegatingHandler
|
||||||
{
|
{
|
||||||
IServiceCollection services = new ServiceCollection();
|
_services.AddTransient<DelegatingHandler, TOne>();
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
_services.AddTransient<DelegatingHandler, TTwo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheServiceProviderReturnsNothing()
|
||||||
|
{
|
||||||
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAnErrorIsReturned()
|
private void ThenAnErrorIsReturned()
|
||||||
{
|
{
|
||||||
_provider.IsError.ShouldBeTrue();
|
_result.IsError.ShouldBeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheDelegatesAreAddedCorrectly()
|
private void ThenTheDelegatesAreAddedCorrectly()
|
||||||
{
|
{
|
||||||
var delegates = _provider.Data;
|
var delegates = _result.Data;
|
||||||
|
|
||||||
var del = delegates[0].Invoke();
|
var del = delegates[0].Invoke();
|
||||||
var handler = (FakeDelegatingHandler) del;
|
var handler = (FakeDelegatingHandler) del;
|
||||||
@ -134,15 +323,15 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
private void ThenItIsPolly(int i)
|
private void ThenItIsPolly(int i)
|
||||||
{
|
{
|
||||||
var delegates = _provider.Data;
|
var delegates = _result.Data;
|
||||||
var del = delegates[i].Invoke();
|
var del = delegates[i].Invoke();
|
||||||
del.ShouldBeOfType<PollyCircuitBreakingDelegatingHandler>();
|
del.ShouldBeOfType<PollyCircuitBreakingDelegatingHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenThereIsDelegatesInProvider(int count)
|
private void ThenThereIsDelegatesInProvider(int count)
|
||||||
{
|
{
|
||||||
_provider.ShouldNotBeNull();
|
_result.ShouldNotBeNull();
|
||||||
_provider.Data.Count.ShouldBe(count);
|
_result.Data.Count.ShouldBe(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheFollowingRequest(DownstreamReRoute request)
|
private void GivenTheFollowingRequest(DownstreamReRoute request)
|
||||||
@ -152,14 +341,19 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
private void WhenIGet()
|
private void WhenIGet()
|
||||||
{
|
{
|
||||||
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
_factory = new DelegatingHandlerHandlerFactory(_loggerFactory.Object, _tracingFactory.Object, _qosProviderHouse.Object, _serviceProvider);
|
_factory = new DelegatingHandlerHandlerFactory(_loggerFactory.Object, _tracingFactory.Object, _qosProviderHouse.Object, _serviceProvider);
|
||||||
_provider = _factory.Get(_request);
|
_result = _factory.Get(_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenNoDelegatesAreInTheProvider()
|
private void ThenNoDelegatesAreInTheProvider()
|
||||||
{
|
{
|
||||||
_provider.ShouldNotBeNull();
|
_result.ShouldNotBeNull();
|
||||||
_provider.Data.Count.ShouldBe(0);
|
_result.Data.Count.ShouldBe(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class FakeTracingHandler : DelegatingHandler, ITracingHandler
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,42 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FakeDelegatingHandlerThree : DelegatingHandler
|
||||||
|
{
|
||||||
|
public FakeDelegatingHandlerThree()
|
||||||
|
{
|
||||||
|
Order = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order { get; private set; }
|
||||||
|
|
||||||
|
public DateTime TimeCalled { get; private set; }
|
||||||
|
|
||||||
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
TimeCalled = DateTime.Now;
|
||||||
|
return Task.FromResult(new HttpResponseMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FakeDelegatingHandlerFour : DelegatingHandler
|
||||||
|
{
|
||||||
|
public FakeDelegatingHandlerFour()
|
||||||
|
{
|
||||||
|
Order = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order { get; private set; }
|
||||||
|
|
||||||
|
public DateTime TimeCalled { get; private set; }
|
||||||
|
|
||||||
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
TimeCalled = DateTime.Now;
|
||||||
|
return Task.FromResult(new HttpResponseMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class FakeDelegatingHandlerTwo : DelegatingHandler
|
public class FakeDelegatingHandlerTwo : DelegatingHandler
|
||||||
{
|
{
|
||||||
public FakeDelegatingHandlerTwo()
|
public FakeDelegatingHandlerTwo()
|
||||||
@ -36,12 +72,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int Order {get;private set;}
|
public int Order {get;private set;}
|
||||||
|
|
||||||
public DateTime TimeCalled {get;private set;}
|
public DateTime TimeCalled {get;private set;}
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
TimeCalled = DateTime.Now;
|
TimeCalled = DateTime.Now;
|
||||||
return new HttpResponseMessage();
|
return Task.FromResult(new HttpResponseMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user