mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-23 00:52:51 +08:00
Feature/automatic routes with sd (#351)
* #340 started looking at supporting automatic routing when using service discovery * #340 getting old routing tests to pass * #340 renamed stuff to provider rather than finder, as its not longer finding anything * #340 working towards supporting dynamic routing * #340 loads of refactoring to make configuration work with dynamic routing * #340 refactor consul config code so the registry class owns it * #340 default to consul to maintain backwards compat * #340 added docs, finished this branches todos
This commit is contained in:
parent
dadb43ef6f
commit
1e2e953b2c
@ -178,3 +178,10 @@ and
|
||||
|
||||
In the example above if you make a request into Ocelot on /goods/delete Ocelot will match /goods/delete ReRoute. Previously it would have
|
||||
matched /goods/{catchAll} (because this is the first ReRoute in the list!).
|
||||
|
||||
Dynamic Routing
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
This feature was requested in `issue 340 <https://github.com/TomPallister/Ocelot/issue/340>`_. The idea is to enable dynamic routing
|
||||
when using a service discovery provider so you don't have to provide the ReRoute config. See the docs :ref:`service-discovery` if
|
||||
this sounds interesting to you.
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. service-discovery:
|
||||
|
||||
Service Discovery
|
||||
=================
|
||||
|
||||
@ -88,3 +90,65 @@ Eureka. One of the services polls Eureka every 30 seconds (default) and gets the
|
||||
When Ocelot asks for a given service it is retrieved from memory so performance is not a big problem. Please note that this code
|
||||
is provided by the Pivotal.Discovery.Client NuGet package so big thanks to them for all the hard work.
|
||||
|
||||
Dynamic Routing
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
This feature was requested in `issue 340 <https://github.com/TomPallister/Ocelot/issue/340>`_. The idea is to enable dynamic routing when using
|
||||
a service discovery provider (see that section of the docs for more info). In this mode Ocelot will use the first segmentof the upstream path to lookup the
|
||||
downstream service with the service discovery provider.
|
||||
|
||||
An example of this would be calling ocelot with a url like https://api.mywebsite.com/product/products. Ocelot will take the first segment of
|
||||
the path which is product and use it as a key to look up the service in consul. If consul returns a service Ocelot will request it on whatever host and
|
||||
port comes back from consul plus the remaining path segments in this case products thus making the downstream call http://hostfromconsul:portfromconsul/products.
|
||||
Ocelot will apprend any query string to the downstream url as normal.
|
||||
|
||||
In order to enable dynamic routing you need to have 0 ReRoutes in your config. At the moment you cannot mix dynamic and configuration ReRoutes. In addition to this you
|
||||
need to specify the Service Discovery provider details as outlined above and the downstream http/https scheme as DownstreamScheme.
|
||||
|
||||
In addition to that you can set RateLimitOptions, QoSOptions, LoadBalancerOptions and HttpHandlerOptions, DownstreamScheme (You might want to call Ocelot on https but
|
||||
talk to private services over http) that will be applied to all of the dynamic ReRoutes.
|
||||
|
||||
The config might look something like
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ReRoutes": [],
|
||||
"Aggregates": [],
|
||||
"GlobalConfiguration": {
|
||||
"RequestIdKey": null,
|
||||
"ServiceDiscoveryProvider": {
|
||||
"Host": "localhost",
|
||||
"Port": 8510,
|
||||
"Type": null,
|
||||
"Token": null,
|
||||
"ConfigurationKey": null
|
||||
},
|
||||
"RateLimitOptions": {
|
||||
"ClientIdHeader": "ClientId",
|
||||
"QuotaExceededMessage": null,
|
||||
"RateLimitCounterPrefix": "ocelot",
|
||||
"DisableRateLimitHeaders": false,
|
||||
"HttpStatusCode": 429
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 0,
|
||||
"DurationOfBreak": 0,
|
||||
"TimeoutValue": 0
|
||||
},
|
||||
"BaseUrl": null,
|
||||
"LoadBalancerOptions": {
|
||||
"Type": "LeastConnection",
|
||||
"Key": null,
|
||||
"Expiry": 0
|
||||
},
|
||||
"DownstreamScheme": "http",
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": false,
|
||||
"UseCookieContainer": false,
|
||||
"UseTracing": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Please take a look through all of the docs to understand these options.
|
@ -9,7 +9,7 @@ namespace Ocelot.Configuration.Builder
|
||||
public class DownstreamReRouteBuilder
|
||||
{
|
||||
private AuthenticationOptions _authenticationOptions;
|
||||
private string _reRouteKey;
|
||||
private string _loadBalancerKey;
|
||||
private string _downstreamPathTemplate;
|
||||
private string _upstreamTemplate;
|
||||
private UpstreamPathTemplate _upstreamTemplatePattern;
|
||||
@ -25,7 +25,6 @@ namespace Ocelot.Configuration.Builder
|
||||
private CacheOptions _fileCacheOptions;
|
||||
private string _downstreamScheme;
|
||||
private LoadBalancerOptions _loadBalancerOptions;
|
||||
private bool _useQos;
|
||||
private QoSOptions _qosOptions;
|
||||
private HttpHandlerOptions _httpHandlerOptions;
|
||||
private bool _enableRateLimiting;
|
||||
@ -41,7 +40,6 @@ namespace Ocelot.Configuration.Builder
|
||||
private List<AddHeader> _addHeadersToDownstream;
|
||||
private List<AddHeader> _addHeadersToUpstream;
|
||||
private bool _dangerousAcceptAnyServerCertificateValidator;
|
||||
private string _qosKey;
|
||||
|
||||
public DownstreamReRouteBuilder()
|
||||
{
|
||||
@ -153,27 +151,15 @@ namespace Ocelot.Configuration.Builder
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithIsQos(bool input)
|
||||
{
|
||||
_useQos = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithQosOptions(QoSOptions input)
|
||||
{
|
||||
_qosOptions = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithReRouteKey(string reRouteKey)
|
||||
public DownstreamReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
|
||||
{
|
||||
_reRouteKey = reRouteKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithQosKey(string qosKey)
|
||||
{
|
||||
_qosKey = qosKey;
|
||||
_loadBalancerKey = loadBalancerKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -267,7 +253,6 @@ namespace Ocelot.Configuration.Builder
|
||||
_httpHandlerOptions,
|
||||
_useServiceDiscovery,
|
||||
_enableRateLimiting,
|
||||
_useQos,
|
||||
_qosOptions,
|
||||
_downstreamScheme,
|
||||
_requestIdHeaderKey,
|
||||
@ -283,12 +268,11 @@ namespace Ocelot.Configuration.Builder
|
||||
_isAuthorised,
|
||||
_authenticationOptions,
|
||||
new PathTemplate(_downstreamPathTemplate),
|
||||
_reRouteKey,
|
||||
_loadBalancerKey,
|
||||
_delegatingHandlers,
|
||||
_addHeadersToDownstream,
|
||||
_addHeadersToUpstream,
|
||||
_dangerousAcceptAnyServerCertificateValidator,
|
||||
_qosKey);
|
||||
_dangerousAcceptAnyServerCertificateValidator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
private int _timeoutValue;
|
||||
|
||||
private string _key;
|
||||
|
||||
public QoSOptionsBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
|
||||
{
|
||||
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
||||
@ -26,9 +28,15 @@
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptionsBuilder WithKey(string input)
|
||||
{
|
||||
_key = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QoSOptions Build()
|
||||
{
|
||||
return new QoSOptions(_exceptionsAllowedBeforeBreaking, _durationOfBreak, _timeoutValue);
|
||||
return new QoSOptions(_exceptionsAllowedBeforeBreaking, _durationOfBreak, _timeoutValue, _key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ namespace Ocelot.Configuration.Builder
|
||||
private bool _isAuthenticated;
|
||||
private bool _isAuthorised;
|
||||
private bool _isCached;
|
||||
private bool _isQoS;
|
||||
private bool _enableRateLimiting;
|
||||
|
||||
public ReRouteOptionsBuilder WithIsCached(bool isCached)
|
||||
@ -26,12 +25,6 @@ namespace Ocelot.Configuration.Builder
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithIsQos(bool isQoS)
|
||||
{
|
||||
_isQoS = isQoS;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
|
||||
{
|
||||
_enableRateLimiting = enableRateLimiting;
|
||||
@ -40,7 +33,7 @@ namespace Ocelot.Configuration.Builder
|
||||
|
||||
public ReRouteOptions Build()
|
||||
{
|
||||
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _isQoS, _enableRateLimiting);
|
||||
return new ReRouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting);
|
||||
}
|
||||
}
|
||||
}
|
@ -105,7 +105,21 @@ namespace Ocelot.Configuration.Creator
|
||||
|
||||
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
|
||||
|
||||
var config = new InternalConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey);
|
||||
var lbOptions = CreateLoadBalancerOptions(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);
|
||||
|
||||
var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);
|
||||
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);
|
||||
|
||||
var config = new InternalConfiguration(reRoutes,
|
||||
_adminPath.Path,
|
||||
serviceProviderConfiguration,
|
||||
fileConfiguration.GlobalConfiguration.RequestIdKey,
|
||||
lbOptions,
|
||||
fileConfiguration.GlobalConfiguration.DownstreamScheme,
|
||||
qosOptions,
|
||||
httpHandlerOptions
|
||||
);
|
||||
|
||||
return new OkResponse<IInternalConfiguration>(config);
|
||||
}
|
||||
@ -160,8 +174,6 @@ namespace Ocelot.Configuration.Creator
|
||||
|
||||
var reRouteKey = CreateReRouteKey(fileReRoute);
|
||||
|
||||
var qosKey = CreateQosKey(fileReRoute);
|
||||
|
||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
||||
|
||||
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
|
||||
@ -172,19 +184,19 @@ namespace Ocelot.Configuration.Creator
|
||||
|
||||
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
|
||||
|
||||
var qosOptions = _qosOptionsCreator.Create(fileReRoute);
|
||||
var qosOptions = _qosOptionsCreator.Create(fileReRoute.QoSOptions, fileReRoute.UpstreamPathTemplate, fileReRoute.UpstreamHttpMethod.ToArray());
|
||||
|
||||
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
||||
|
||||
var region = _regionCreator.Create(fileReRoute);
|
||||
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute);
|
||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute.HttpHandlerOptions);
|
||||
|
||||
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
|
||||
|
||||
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
|
||||
|
||||
var lbOptions = CreateLoadBalancerOptions(fileReRoute);
|
||||
var lbOptions = CreateLoadBalancerOptions(fileReRoute.LoadBalancerOptions);
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithKey(fileReRoute.Key)
|
||||
@ -205,9 +217,7 @@ namespace Ocelot.Configuration.Creator
|
||||
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
||||
.WithLoadBalancerOptions(lbOptions)
|
||||
.WithDownstreamAddresses(downstreamAddresses)
|
||||
.WithReRouteKey(reRouteKey)
|
||||
.WithQosKey(qosKey)
|
||||
.WithIsQos(fileReRouteOptions.IsQos)
|
||||
.WithLoadBalancerKey(reRouteKey)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
|
||||
.WithRateLimitOptions(rateLimitOption)
|
||||
@ -226,9 +236,13 @@ namespace Ocelot.Configuration.Creator
|
||||
return reRoute;
|
||||
}
|
||||
|
||||
private LoadBalancerOptions CreateLoadBalancerOptions(FileReRoute fileReRoute)
|
||||
private LoadBalancerOptions CreateLoadBalancerOptions(FileLoadBalancerOptions options)
|
||||
{
|
||||
return new LoadBalancerOptions(fileReRoute.LoadBalancerOptions.Type, fileReRoute.LoadBalancerOptions.Key, fileReRoute.LoadBalancerOptions.Expiry);
|
||||
return new LoadBalancerOptionsBuilder()
|
||||
.WithType(options.Type)
|
||||
.WithKey(options.Key)
|
||||
.WithExpiryInMs(options.Expiry)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private string CreateReRouteKey(FileReRoute fileReRoute)
|
||||
@ -238,14 +252,7 @@ namespace Ocelot.Configuration.Creator
|
||||
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
|
||||
}
|
||||
|
||||
return CreateQosKey(fileReRoute);
|
||||
}
|
||||
|
||||
private string CreateQosKey(FileReRoute fileReRoute)
|
||||
{
|
||||
//note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
|
||||
var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
|
||||
return loadBalancerKey;
|
||||
return $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,19 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator
|
||||
{
|
||||
private IServiceTracer _tracer;
|
||||
private readonly IServiceTracer _tracer;
|
||||
|
||||
public HttpHandlerOptionsCreator(IServiceTracer tracer)
|
||||
{
|
||||
_tracer = tracer;
|
||||
}
|
||||
|
||||
public HttpHandlerOptions Create(FileReRoute fileReRoute)
|
||||
public HttpHandlerOptions Create(FileHttpHandlerOptions options)
|
||||
{
|
||||
var useTracing = _tracer.GetType() != typeof(FakeServiceTracer) ? fileReRoute.HttpHandlerOptions.UseTracing : false;
|
||||
var useTracing = _tracer.GetType() != typeof(FakeServiceTracer) && options.UseTracing;
|
||||
|
||||
return new HttpHandlerOptions(fileReRoute.HttpHandlerOptions.AllowAutoRedirect,
|
||||
fileReRoute.HttpHandlerOptions.UseCookieContainer, useTracing);
|
||||
return new HttpHandlerOptions(options.AllowAutoRedirect,
|
||||
options.UseCookieContainer, useTracing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ namespace Ocelot.Configuration.Creator
|
||||
/// </summary>
|
||||
public interface IHttpHandlerOptionsCreator
|
||||
{
|
||||
HttpHandlerOptions Create(FileReRoute fileReRoute);
|
||||
HttpHandlerOptions Create(FileHttpHandlerOptions fileReRoute);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public interface IQoSOptionsCreator
|
||||
{
|
||||
QoSOptions Create(FileReRoute fileReRoute);
|
||||
QoSOptions Create(FileQoSOptions options);
|
||||
QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods);
|
||||
QoSOptions Create(QoSOptions options, string pathTemplate, string[] httpMethods);
|
||||
}
|
||||
}
|
@ -1,17 +1,47 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
|
||||
namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
using System.Linq;
|
||||
|
||||
public class QoSOptionsCreator : IQoSOptionsCreator
|
||||
{
|
||||
public QoSOptions Create(FileReRoute fileReRoute)
|
||||
public QoSOptions Create(FileQoSOptions options)
|
||||
{
|
||||
return new QoSOptionsBuilder()
|
||||
.WithExceptionsAllowedBeforeBreaking(fileReRoute.QoSOptions.ExceptionsAllowedBeforeBreaking)
|
||||
.WithDurationOfBreak(fileReRoute.QoSOptions.DurationOfBreak)
|
||||
.WithTimeoutValue(fileReRoute.QoSOptions.TimeoutValue)
|
||||
.WithExceptionsAllowedBeforeBreaking(options.ExceptionsAllowedBeforeBreaking)
|
||||
.WithDurationOfBreak(options.DurationOfBreak)
|
||||
.WithTimeoutValue(options.TimeoutValue)
|
||||
.Build();
|
||||
}
|
||||
|
||||
public QoSOptions Create(FileQoSOptions options, string pathTemplate, string[] httpMethods)
|
||||
{
|
||||
var key = CreateKey(pathTemplate, httpMethods);
|
||||
|
||||
return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking);
|
||||
}
|
||||
|
||||
public QoSOptions Create(QoSOptions options, string pathTemplate, string[] httpMethods)
|
||||
{
|
||||
var key = CreateKey(pathTemplate, httpMethods);
|
||||
|
||||
return Map(key, options.TimeoutValue, options.DurationOfBreak, options.ExceptionsAllowedBeforeBreaking);
|
||||
}
|
||||
|
||||
private QoSOptions Map(string key, int timeoutValue, int durationOfBreak, int exceptionsAllowedBeforeBreaking)
|
||||
{
|
||||
return new QoSOptionsBuilder()
|
||||
.WithExceptionsAllowedBeforeBreaking(exceptionsAllowedBeforeBreaking)
|
||||
.WithDurationOfBreak(durationOfBreak)
|
||||
.WithTimeoutValue(timeoutValue)
|
||||
.WithKey(key)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private string CreateKey(string pathTemplate, string[] httpMethods)
|
||||
{
|
||||
return $"{pathTemplate.FirstOrDefault()}|{string.Join(",", httpMethods)}";
|
||||
}
|
||||
}
|
||||
}
|
@ -10,14 +10,12 @@ namespace Ocelot.Configuration.Creator
|
||||
var isAuthenticated = IsAuthenticated(fileReRoute);
|
||||
var isAuthorised = IsAuthorised(fileReRoute);
|
||||
var isCached = IsCached(fileReRoute);
|
||||
var isQos = IsQoS(fileReRoute);
|
||||
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
|
||||
|
||||
var options = new ReRouteOptionsBuilder()
|
||||
.WithIsAuthenticated(isAuthenticated)
|
||||
.WithIsAuthorised(isAuthorised)
|
||||
.WithIsCached(isCached)
|
||||
.WithIsQos(isQos)
|
||||
.WithRateLimiting(enableRateLimiting)
|
||||
.Build();
|
||||
|
||||
@ -29,11 +27,6 @@ namespace Ocelot.Configuration.Creator
|
||||
return (fileReRoute.RateLimitOptions != null && fileReRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
|
||||
}
|
||||
|
||||
private bool IsQoS(FileReRoute fileReRoute)
|
||||
{
|
||||
return fileReRoute.QoSOptions?.ExceptionsAllowedBeforeBreaking > 0 && fileReRoute.QoSOptions?.TimeoutValue > 0;
|
||||
}
|
||||
|
||||
private bool IsAuthenticated(FileReRoute fileReRoute)
|
||||
{
|
||||
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.AuthenticationProviderKey);
|
||||
|
@ -7,12 +7,12 @@ namespace Ocelot.Configuration.Creator
|
||||
{
|
||||
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration)
|
||||
{
|
||||
//todo log or return error here dont just default to something that wont work..
|
||||
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||
var port = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||
var host = globalConfiguration?.ServiceDiscoveryProvider?.Host ?? "consul";
|
||||
|
||||
return new ServiceProviderConfigurationBuilder()
|
||||
.WithHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
|
||||
.WithPort(serviceProviderPort)
|
||||
.WithHost(host)
|
||||
.WithPort(port)
|
||||
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
|
||||
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
|
||||
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
|
||||
|
@ -16,8 +16,7 @@ namespace Ocelot.Configuration
|
||||
HttpHandlerOptions httpHandlerOptions,
|
||||
bool useServiceDiscovery,
|
||||
bool enableEndpointEndpointRateLimiting,
|
||||
bool isQos,
|
||||
QoSOptions qosOptionsOptions,
|
||||
QoSOptions qosOptions,
|
||||
string downstreamScheme,
|
||||
string requestIdKey,
|
||||
bool isCached,
|
||||
@ -36,8 +35,7 @@ namespace Ocelot.Configuration
|
||||
List<string> delegatingHandlers,
|
||||
List<AddHeader> addHeadersToDownstream,
|
||||
List<AddHeader> addHeadersToUpstream,
|
||||
bool dangerousAcceptAnyServerCertificateValidator,
|
||||
string qosKey)
|
||||
bool dangerousAcceptAnyServerCertificateValidator)
|
||||
{
|
||||
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||
AddHeadersToDownstream = addHeadersToDownstream;
|
||||
@ -51,8 +49,7 @@ namespace Ocelot.Configuration
|
||||
HttpHandlerOptions = httpHandlerOptions;
|
||||
UseServiceDiscovery = useServiceDiscovery;
|
||||
EnableEndpointEndpointRateLimiting = enableEndpointEndpointRateLimiting;
|
||||
IsQos = isQos;
|
||||
QosOptionsOptions = qosOptionsOptions;
|
||||
QosOptions = qosOptions;
|
||||
DownstreamScheme = downstreamScheme;
|
||||
RequestIdKey = requestIdKey;
|
||||
IsCached = isCached;
|
||||
@ -69,10 +66,8 @@ namespace Ocelot.Configuration
|
||||
DownstreamPathTemplate = downstreamPathTemplate;
|
||||
LoadBalancerKey = loadBalancerKey;
|
||||
AddHeadersToUpstream = addHeadersToUpstream;
|
||||
QosKey = qosKey;
|
||||
}
|
||||
|
||||
public string QosKey { get; }
|
||||
public string Key { get; }
|
||||
public PathTemplate UpstreamPathTemplate { get; }
|
||||
public List<HeaderFindAndReplace> UpstreamHeadersFindAndReplace { get; }
|
||||
@ -82,8 +77,7 @@ namespace Ocelot.Configuration
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
public bool UseServiceDiscovery { get; }
|
||||
public bool EnableEndpointEndpointRateLimiting { get; }
|
||||
public bool IsQos { get; }
|
||||
public QoSOptions QosOptionsOptions { get; }
|
||||
public QoSOptions QosOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public string RequestIdKey { get; }
|
||||
public bool IsCached { get; }
|
||||
|
@ -6,6 +6,9 @@
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider();
|
||||
RateLimitOptions = new FileRateLimitOptions();
|
||||
LoadBalancerOptions = new FileLoadBalancerOptions();
|
||||
QoSOptions = new FileQoSOptions();
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions();
|
||||
}
|
||||
|
||||
public string RequestIdKey { get; set; }
|
||||
@ -14,6 +17,14 @@
|
||||
|
||||
public FileRateLimitOptions RateLimitOptions { get; set; }
|
||||
|
||||
public FileQoSOptions QoSOptions { get; set; }
|
||||
|
||||
public string BaseUrl { get ;set; }
|
||||
|
||||
public FileLoadBalancerOptions LoadBalancerOptions { get; set; }
|
||||
|
||||
public string DownstreamScheme { get; set; }
|
||||
|
||||
public FileHttpHandlerOptions HttpHandlerOptions { get; set; }
|
||||
}
|
||||
}
|
||||
|
32
src/Ocelot/Configuration/HttpHandlerOptionsBuilder.cs
Normal file
32
src/Ocelot/Configuration/HttpHandlerOptionsBuilder.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
public class HttpHandlerOptionsBuilder
|
||||
{
|
||||
private bool _allowAutoRedirect;
|
||||
private bool _useCookieContainer;
|
||||
private bool _useTracing;
|
||||
|
||||
public HttpHandlerOptionsBuilder WithAllowAutoRedirect(bool input)
|
||||
{
|
||||
_allowAutoRedirect = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpHandlerOptionsBuilder WithUseCookieContainer(bool input)
|
||||
{
|
||||
_useCookieContainer = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpHandlerOptionsBuilder WithUseTracing(bool input)
|
||||
{
|
||||
_useTracing = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpHandlerOptions Build()
|
||||
{
|
||||
return new HttpHandlerOptions(_allowAutoRedirect, _useCookieContainer, _useTracing);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,8 +5,19 @@ namespace Ocelot.Configuration
|
||||
public interface IInternalConfiguration
|
||||
{
|
||||
List<ReRoute> ReRoutes { get; }
|
||||
|
||||
string AdministrationPath {get;}
|
||||
|
||||
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
||||
|
||||
string RequestId {get;}
|
||||
|
||||
LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
|
||||
string DownstreamScheme { get; }
|
||||
|
||||
QoSOptions QoSOptions { get; }
|
||||
|
||||
HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,33 @@ namespace Ocelot.Configuration
|
||||
{
|
||||
public class InternalConfiguration : IInternalConfiguration
|
||||
{
|
||||
public InternalConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId)
|
||||
public InternalConfiguration(
|
||||
List<ReRoute> reRoutes,
|
||||
string administrationPath,
|
||||
ServiceProviderConfiguration serviceProviderConfiguration,
|
||||
string requestId,
|
||||
LoadBalancerOptions loadBalancerOptions,
|
||||
string downstreamScheme,
|
||||
QoSOptions qoSOptions,
|
||||
HttpHandlerOptions httpHandlerOptions)
|
||||
{
|
||||
ReRoutes = reRoutes;
|
||||
AdministrationPath = administrationPath;
|
||||
ServiceProviderConfiguration = serviceProviderConfiguration;
|
||||
RequestId = requestId;
|
||||
LoadBalancerOptions = loadBalancerOptions;
|
||||
DownstreamScheme = downstreamScheme;
|
||||
QoSOptions = qoSOptions;
|
||||
HttpHandlerOptions = httpHandlerOptions;
|
||||
}
|
||||
|
||||
public List<ReRoute> ReRoutes { get; }
|
||||
public string AdministrationPath {get;}
|
||||
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
||||
public string RequestId {get;}
|
||||
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public QoSOptions QoSOptions { get; }
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
}
|
||||
}
|
||||
|
32
src/Ocelot/Configuration/LoadBalancerOptionsBuilder.cs
Normal file
32
src/Ocelot/Configuration/LoadBalancerOptionsBuilder.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace Ocelot.Configuration
|
||||
{
|
||||
public class LoadBalancerOptionsBuilder
|
||||
{
|
||||
private string _type;
|
||||
private string _key;
|
||||
private int _expiryInMs;
|
||||
|
||||
public LoadBalancerOptionsBuilder WithType(string type)
|
||||
{
|
||||
_type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoadBalancerOptionsBuilder WithKey(string key)
|
||||
{
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoadBalancerOptionsBuilder WithExpiryInMs(int expiryInMs)
|
||||
{
|
||||
_expiryInMs = expiryInMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoadBalancerOptions Build()
|
||||
{
|
||||
return new LoadBalancerOptions(_type, _key, _expiryInMs);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,12 +8,14 @@ namespace Ocelot.Configuration
|
||||
int exceptionsAllowedBeforeBreaking,
|
||||
int durationofBreak,
|
||||
int timeoutValue,
|
||||
string key,
|
||||
TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
||||
DurationOfBreak = durationofBreak;
|
||||
TimeoutValue = timeoutValue;
|
||||
TimeoutStrategy = timeoutStrategy;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public int ExceptionsAllowedBeforeBreaking { get; }
|
||||
@ -23,5 +25,8 @@ namespace Ocelot.Configuration
|
||||
public int TimeoutValue { get; }
|
||||
|
||||
public TimeoutStrategy TimeoutStrategy { get; }
|
||||
|
||||
public bool UseQos => ExceptionsAllowedBeforeBreaking > 0 && TimeoutValue > 0;
|
||||
public string Key { get; }
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,17 @@ namespace Ocelot.Configuration
|
||||
{
|
||||
public class ReRouteOptions
|
||||
{
|
||||
public ReRouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isQos, bool isEnableRateLimiting)
|
||||
public ReRouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isEnableRateLimiting)
|
||||
{
|
||||
IsAuthenticated = isAuthenticated;
|
||||
IsAuthorised = isAuthorised;
|
||||
IsCached = isCached;
|
||||
IsQos = isQos;
|
||||
EnableRateLimiting = isEnableRateLimiting;
|
||||
}
|
||||
|
||||
public bool IsAuthenticated { get; private set; }
|
||||
public bool IsAuthorised { get; private set; }
|
||||
public bool IsCached { get; private set; }
|
||||
public bool IsQos { get; private set; }
|
||||
public bool EnableRateLimiting { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@ -30,20 +30,18 @@ namespace Ocelot.Configuration.Repository
|
||||
var internalConfig = repo.Get();
|
||||
|
||||
_configurationKey = "InternalConfiguration";
|
||||
var consulHost = "localhost";
|
||||
var consulPort = 8500;
|
||||
|
||||
string token = null;
|
||||
|
||||
if (!internalConfig.IsError)
|
||||
{
|
||||
consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host;
|
||||
consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort;
|
||||
token = internalConfig.Data.ServiceProviderConfiguration?.Token;
|
||||
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.ConfigurationKey) ?
|
||||
internalConfig.Data.ServiceProviderConfiguration?.ConfigurationKey : _configurationKey;
|
||||
token = internalConfig.Data.ServiceProviderConfiguration.Token;
|
||||
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey) ?
|
||||
internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey : _configurationKey;
|
||||
}
|
||||
|
||||
var config = new ConsulRegistryConfiguration(consulHost, consulPort, _configurationKey, token);
|
||||
var config = new ConsulRegistryConfiguration(internalConfig.Data.ServiceProviderConfiguration.Host,
|
||||
internalConfig.Data.ServiceProviderConfiguration.Port, _configurationKey, token);
|
||||
|
||||
_consul = factory.Get(config);
|
||||
}
|
||||
|
@ -103,7 +103,9 @@ namespace Ocelot.DependencyInjection
|
||||
_services.TryAddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
||||
_services.TryAddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
|
||||
_services.TryAddSingleton<IDownstreamPathPlaceholderReplacer, DownstreamTemplatePathPlaceholderReplacer>();
|
||||
_services.TryAddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
|
||||
_services.AddSingleton<IDownstreamRouteProvider, DownstreamRouteFinder>();
|
||||
_services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>();
|
||||
_services.TryAddSingleton<IDownstreamRouteProviderFactory, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteProviderFactory>();
|
||||
_services.TryAddSingleton<IHttpRequester, HttpClientHttpRequester>();
|
||||
_services.TryAddSingleton<IHttpResponder, HttpContextResponder>();
|
||||
_services.TryAddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>();
|
||||
|
@ -0,0 +1,97 @@
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Configuration;
|
||||
using Configuration.Builder;
|
||||
using Configuration.Creator;
|
||||
using Configuration.File;
|
||||
using LoadBalancer.LoadBalancers;
|
||||
using Responses;
|
||||
using UrlMatcher;
|
||||
|
||||
public class DownstreamRouteCreator : IDownstreamRouteProvider
|
||||
{
|
||||
private readonly IQoSOptionsCreator _qoSOptionsCreator;
|
||||
|
||||
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
|
||||
{
|
||||
_qoSOptionsCreator = qoSOptionsCreator;
|
||||
}
|
||||
|
||||
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
{
|
||||
var serviceName = GetServiceName(upstreamUrlPath);
|
||||
|
||||
var downstreamPath = GetDownstreamPath(upstreamUrlPath);
|
||||
|
||||
if(HasQueryString(downstreamPath))
|
||||
{
|
||||
downstreamPath = RemoveQueryString(downstreamPath);
|
||||
}
|
||||
|
||||
var downstreamPathForKeys = $"/{serviceName}{downstreamPath}";
|
||||
|
||||
var loadBalancerKey = CreateLoadBalancerKey(downstreamPathForKeys, upstreamHttpMethod, configuration.LoadBalancerOptions);
|
||||
|
||||
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new []{ upstreamHttpMethod });
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithServiceName(serviceName)
|
||||
.WithLoadBalancerKey(loadBalancerKey)
|
||||
.WithDownstreamPathTemplate(downstreamPath)
|
||||
.WithUseServiceDiscovery(true)
|
||||
.WithHttpHandlerOptions(configuration.HttpHandlerOptions)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithDownstreamScheme(configuration.DownstreamScheme)
|
||||
.WithLoadBalancerOptions(configuration.LoadBalancerOptions)
|
||||
.Build();
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string>(){ upstreamHttpMethod })
|
||||
.Build();
|
||||
|
||||
return new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
||||
}
|
||||
|
||||
private static string RemoveQueryString(string downstreamPath)
|
||||
{
|
||||
return downstreamPath
|
||||
.Substring(0, downstreamPath.IndexOf('?'));
|
||||
}
|
||||
|
||||
private static bool HasQueryString(string downstreamPath)
|
||||
{
|
||||
return downstreamPath.Contains("?");
|
||||
}
|
||||
|
||||
private static string GetDownstreamPath(string upstreamUrlPath)
|
||||
{
|
||||
return upstreamUrlPath
|
||||
.Substring(upstreamUrlPath.IndexOf('/', 1));
|
||||
}
|
||||
|
||||
private static string GetServiceName(string upstreamUrlPath)
|
||||
{
|
||||
return upstreamUrlPath
|
||||
.Substring(1, upstreamUrlPath.IndexOf('/', 1))
|
||||
.TrimEnd('/');
|
||||
}
|
||||
|
||||
private string CreateLoadBalancerKey(string downstreamTemplatePath, string httpMethod, LoadBalancerOptions loadBalancerOptions)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(loadBalancerOptions.Type) && !string.IsNullOrEmpty(loadBalancerOptions.Key) && loadBalancerOptions.Type == nameof(CookieStickySessions))
|
||||
{
|
||||
return $"{nameof(CookieStickySessions)}:{loadBalancerOptions.Key}";
|
||||
}
|
||||
|
||||
return CreateQoSKey(downstreamTemplatePath, httpMethod);
|
||||
}
|
||||
|
||||
private string CreateQoSKey(string downstreamTemplatePath, string httpMethod)
|
||||
{
|
||||
var loadBalancerKey = $"{downstreamTemplatePath}|{httpMethod}";
|
||||
return loadBalancerKey;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public class DownstreamRouteFinder : IDownstreamRouteFinder
|
||||
public class DownstreamRouteFinder : IDownstreamRouteProvider
|
||||
{
|
||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
|
||||
@ -18,7 +18,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
|
||||
}
|
||||
|
||||
public Response<DownstreamRoute> FindDownstreamRoute(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
public Response<DownstreamRoute> Get(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||
{
|
||||
var downstreamRoutes = new List<DownstreamRoute>();
|
||||
|
||||
|
@ -0,0 +1,38 @@
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
public class DownstreamRouteProviderFactory : IDownstreamRouteProviderFactory
|
||||
{
|
||||
private readonly Dictionary<string, IDownstreamRouteProvider> _providers;
|
||||
|
||||
public DownstreamRouteProviderFactory(IServiceProvider provider)
|
||||
{
|
||||
_providers = provider.GetServices<IDownstreamRouteProvider>().ToDictionary(x => x.GetType().Name);
|
||||
}
|
||||
|
||||
public IDownstreamRouteProvider Get(IInternalConfiguration config)
|
||||
{
|
||||
if(!config.ReRoutes.Any() && IsServiceDiscovery(config.ServiceProviderConfiguration))
|
||||
{
|
||||
return _providers[nameof(DownstreamRouteCreator)];
|
||||
}
|
||||
|
||||
return _providers[nameof(DownstreamRouteFinder)];
|
||||
}
|
||||
|
||||
private bool IsServiceDiscovery(ServiceProviderConfiguration config)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(config?.Host) || config?.Port > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public interface IDownstreamRouteFinder
|
||||
{
|
||||
Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
public interface IDownstreamRouteProvider
|
||||
{
|
||||
Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||
{
|
||||
using Configuration;
|
||||
|
||||
public interface IDownstreamRouteProviderFactory
|
||||
{
|
||||
IDownstreamRouteProvider Get(IInternalConfiguration config);
|
||||
}
|
||||
}
|
@ -12,13 +12,13 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
||||
public class DownstreamRouteFinderMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
||||
private readonly IDownstreamRouteProviderFactory _factory;
|
||||
private readonly IInternalConfigurationRepository _repo;
|
||||
private readonly IMultiplexer _multiplexer;
|
||||
|
||||
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
IDownstreamRouteFinder downstreamRouteFinder,
|
||||
IDownstreamRouteProviderFactory downstreamRouteFinder,
|
||||
IInternalConfigurationRepository repo,
|
||||
IMultiplexer multiplexer)
|
||||
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
|
||||
@ -26,7 +26,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
||||
_repo = repo;
|
||||
_multiplexer = multiplexer;
|
||||
_next = next;
|
||||
_downstreamRouteFinder = downstreamRouteFinder;
|
||||
_factory = downstreamRouteFinder;
|
||||
}
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
@ -35,20 +35,11 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
||||
|
||||
var upstreamHost = context.HttpContext.Request.Headers["Host"];
|
||||
|
||||
var configuration = _repo.Get();
|
||||
|
||||
if (configuration.IsError)
|
||||
{
|
||||
Logger.LogWarning($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
|
||||
SetPipelineError(context, configuration.Errors);
|
||||
return;
|
||||
}
|
||||
|
||||
context.ServiceProviderConfiguration = configuration.Data.ServiceProviderConfiguration;
|
||||
|
||||
Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
|
||||
|
||||
var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.HttpContext.Request.Method, configuration.Data, upstreamHost);
|
||||
var provider = _factory.Get(context.Configuration);
|
||||
|
||||
var downstreamRoute = provider.Get(upstreamUrlPath, context.HttpContext.Request.Method, context.Configuration, upstreamHost);
|
||||
|
||||
if (downstreamRoute.IsError)
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
|
||||
private static bool ServiceFabricRequest(DownstreamContext context)
|
||||
{
|
||||
return context.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery;
|
||||
return context.Configuration.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery;
|
||||
}
|
||||
|
||||
private static bool RequestForStatefullService(string query)
|
||||
|
@ -9,6 +9,8 @@ using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.Errors.Middleware
|
||||
{
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Catches all unhandled exceptions thrown by middleware, logs and returns a 500
|
||||
/// </summary>
|
||||
@ -33,7 +35,19 @@ namespace Ocelot.Errors.Middleware
|
||||
{
|
||||
try
|
||||
{
|
||||
TrySetGlobalRequestId(context);
|
||||
//try and get the global request id and set it for logs...
|
||||
//should this basically be immutable per request...i guess it should!
|
||||
//first thing is get config
|
||||
var configuration = _configRepo.Get();
|
||||
|
||||
if (configuration.IsError)
|
||||
{
|
||||
throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
|
||||
}
|
||||
|
||||
TrySetGlobalRequestId(context, configuration.Data);
|
||||
|
||||
context.Configuration = configuration.Data;
|
||||
|
||||
Logger.LogDebug("ocelot pipeline started");
|
||||
|
||||
@ -53,19 +67,9 @@ namespace Ocelot.Errors.Middleware
|
||||
Logger.LogDebug("ocelot pipeline finished");
|
||||
}
|
||||
|
||||
private void TrySetGlobalRequestId(DownstreamContext context)
|
||||
private void TrySetGlobalRequestId(DownstreamContext context, IInternalConfiguration configuration)
|
||||
{
|
||||
//try and get the global request id and set it for logs...
|
||||
//should this basically be immutable per request...i guess it should!
|
||||
//first thing is get config
|
||||
var configuration = _configRepo.Get();
|
||||
|
||||
if(configuration.IsError)
|
||||
{
|
||||
throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
|
||||
}
|
||||
|
||||
var key = configuration.Data.RequestId;
|
||||
var key = configuration.RequestId;
|
||||
|
||||
if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
|
||||
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
||||
{
|
||||
//todo no point spinning a task up here, also first or default could be null..
|
||||
//todo first or default could be null..
|
||||
if (_services == null || _services.Count == 0)
|
||||
{
|
||||
return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer"));
|
||||
|
@ -22,7 +22,7 @@ namespace Ocelot.LoadBalancer.Middleware
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.ServiceProviderConfiguration);
|
||||
var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.Configuration.ServiceProviderConfiguration);
|
||||
if(loadBalancer.IsError)
|
||||
{
|
||||
Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
|
||||
|
@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Request.Middleware;
|
||||
|
||||
namespace Ocelot.Middleware
|
||||
@ -20,8 +17,6 @@ namespace Ocelot.Middleware
|
||||
|
||||
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
|
||||
|
||||
public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
|
||||
|
||||
public HttpContext HttpContext { get; }
|
||||
|
||||
public DownstreamReRoute DownstreamReRoute { get; set; }
|
||||
@ -32,6 +27,8 @@ namespace Ocelot.Middleware
|
||||
|
||||
public List<Error> Errors { get; }
|
||||
|
||||
public IInternalConfiguration Configuration { get; set; }
|
||||
|
||||
public bool IsError => Errors.Count > 0;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace Ocelot.Middleware.Multiplexer
|
||||
var downstreamContext = new DownstreamContext(context.HttpContext)
|
||||
{
|
||||
TemplatePlaceholderNameAndValues = context.TemplatePlaceholderNameAndValues,
|
||||
ServiceProviderConfiguration = context.ServiceProviderConfiguration,
|
||||
Configuration = context.Configuration,
|
||||
DownstreamReRoute = reRoute.DownstreamReRoute[i],
|
||||
};
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace Ocelot.Requester
|
||||
handlers.Add(() => (DelegatingHandler)_factory.Get());
|
||||
}
|
||||
|
||||
if (request.IsQos)
|
||||
if (request.QosOptions.UseQos)
|
||||
{
|
||||
var qosProvider = _qosProviderHouse.Get(request);
|
||||
|
||||
|
@ -58,9 +58,9 @@ namespace Ocelot.Requester
|
||||
.LogWarning($"You have ignored all SSL warnings by using DangerousAcceptAnyServerCertificateValidator for this DownstreamReRoute, UpstreamPathTemplate: {context.DownstreamReRoute.UpstreamPathTemplate}, DownstreamPathTemplate: {context.DownstreamReRoute.DownstreamPathTemplate}");
|
||||
}
|
||||
|
||||
var timeout = context.DownstreamReRoute.QosOptionsOptions.TimeoutValue == 0
|
||||
var timeout = context.DownstreamReRoute.QosOptions.TimeoutValue == 0
|
||||
? _defaultTimeout
|
||||
: TimeSpan.FromMilliseconds(context.DownstreamReRoute.QosOptionsOptions.TimeoutValue);
|
||||
: TimeSpan.FromMilliseconds(context.DownstreamReRoute.QosOptions.TimeoutValue);
|
||||
|
||||
_httpClient = new HttpClient(CreateHttpMessageHandler(httpclientHandler, context.DownstreamReRoute))
|
||||
{
|
||||
|
@ -19,15 +19,15 @@ namespace Ocelot.Requester.QoS
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();
|
||||
|
||||
_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.TimeoutValue), reRoute.QosOptionsOptions.TimeoutStrategy);
|
||||
_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptions.TimeoutValue), reRoute.QosOptions.TimeoutStrategy);
|
||||
|
||||
_circuitBreakerPolicy = Policy
|
||||
.Handle<HttpRequestException>()
|
||||
.Or<TimeoutRejectedException>()
|
||||
.Or<TimeoutException>()
|
||||
.CircuitBreakerAsync(
|
||||
exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking,
|
||||
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak),
|
||||
exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking,
|
||||
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptions.DurationOfBreak),
|
||||
onBreak: (ex, breakDelay) =>
|
||||
{
|
||||
_logger.LogError(
|
||||
|
@ -14,7 +14,7 @@ namespace Ocelot.Requester.QoS
|
||||
|
||||
public IQoSProvider Get(DownstreamReRoute reRoute)
|
||||
{
|
||||
if (reRoute.IsQos)
|
||||
if (reRoute.QosOptions.UseQos)
|
||||
{
|
||||
return new PollyQoSProvider(reRoute, _loggerFactory);
|
||||
}
|
||||
|
@ -21,26 +21,26 @@ namespace Ocelot.Requester.QoS
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_qoSProviders.TryGetValue(reRoute.QosKey, out var qosProvider))
|
||||
if (_qoSProviders.TryGetValue(reRoute.QosOptions.Key, out var qosProvider))
|
||||
{
|
||||
if (reRoute.IsQos && qosProvider.CircuitBreaker == null)
|
||||
if (reRoute.QosOptions.UseQos && qosProvider.CircuitBreaker == null)
|
||||
{
|
||||
qosProvider = _qoSProviderFactory.Get(reRoute);
|
||||
Add(reRoute.QosKey, qosProvider);
|
||||
Add(reRoute.QosOptions.Key, qosProvider);
|
||||
}
|
||||
|
||||
return new OkResponse<IQoSProvider>(_qoSProviders[reRoute.QosKey]);
|
||||
return new OkResponse<IQoSProvider>(_qoSProviders[reRoute.QosOptions.Key]);
|
||||
}
|
||||
|
||||
qosProvider = _qoSProviderFactory.Get(reRoute);
|
||||
Add(reRoute.QosKey, qosProvider);
|
||||
Add(reRoute.QosOptions.Key, qosProvider);
|
||||
return new OkResponse<IQoSProvider>(qosProvider);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<IQoSProvider>(new List<Ocelot.Errors.Error>()
|
||||
{
|
||||
new UnableToFindQoSProviderError($"unabe to find qos provider for {reRoute.QosKey}, exception was {ex}")
|
||||
new UnableToFindQoSProviderError($"unabe to find qos provider for {reRoute.QosOptions.Key}, exception was {ex}")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ namespace Ocelot.ServiceDiscovery.Configuration
|
||||
{
|
||||
public ConsulRegistryConfiguration(string host, int port, string keyOfServiceInConsul, string token)
|
||||
{
|
||||
Host = host;
|
||||
Port = port;
|
||||
Host = string.IsNullOrEmpty(host) ? "localhost" : host;
|
||||
Port = port > 0 ? port : 8500;
|
||||
KeyOfServiceInConsul = keyOfServiceInConsul;
|
||||
Token = token;
|
||||
}
|
||||
|
@ -22,12 +22,7 @@ namespace Ocelot.ServiceDiscovery.Providers
|
||||
{;
|
||||
_logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
|
||||
|
||||
var consulHost = string.IsNullOrEmpty(config?.Host) ? "localhost" : config.Host;
|
||||
|
||||
var consulPort = config?.Port ?? 8500;
|
||||
|
||||
_config = new ConsulRegistryConfiguration(consulHost, consulPort, config?.KeyOfServiceInConsul, config?.Token);
|
||||
|
||||
_config = config;
|
||||
_consul = clientFactory.Get(_config);
|
||||
}
|
||||
|
||||
|
@ -208,6 +208,121 @@ namespace Ocelot.AcceptanceTests
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_handle_request_to_consul_for_downstream_service_and_make_request_no_re_routes()
|
||||
{
|
||||
const int consulPort = 8513;
|
||||
const string serviceName = "web";
|
||||
const int downstreamServicePort = 8087;
|
||||
var downstreamServiceOneUrl = $"http://localhost:{downstreamServicePort}";
|
||||
var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
|
||||
var serviceEntryOne = new ServiceEntry()
|
||||
{
|
||||
Service = new AgentService()
|
||||
{
|
||||
Service = serviceName,
|
||||
Address = "localhost",
|
||||
Port = downstreamServicePort,
|
||||
ID = "web_90_0_2_224_8080",
|
||||
Tags = new[] {"version-v1"}
|
||||
},
|
||||
};
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
GlobalConfiguration = new FileGlobalConfiguration
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = consulPort
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = true,
|
||||
UseCookieContainer = true,
|
||||
UseTracing = false
|
||||
},
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
TimeoutValue = 100,
|
||||
DurationOfBreak = 1000,
|
||||
ExceptionsAllowedBeforeBreaking = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/something", 200, "Hello from Laura"))
|
||||
.And(x => x.GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
|
||||
.And(x => x.GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/web/something"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_consul_service_discovery_and_load_balance_request_no_re_routes()
|
||||
{
|
||||
var consulPort = 8510;
|
||||
var serviceName = "product";
|
||||
var serviceOnePort = 50888;
|
||||
var serviceTwoPort = 50889;
|
||||
var downstreamServiceOneUrl = $"http://localhost:{serviceOnePort}";
|
||||
var downstreamServiceTwoUrl = $"http://localhost:{serviceTwoPort}";
|
||||
var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
|
||||
var serviceEntryOne = new ServiceEntry()
|
||||
{
|
||||
Service = new AgentService()
|
||||
{
|
||||
Service = serviceName,
|
||||
Address = "localhost",
|
||||
Port = serviceOnePort,
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Tags = new string[0]
|
||||
},
|
||||
};
|
||||
var serviceEntryTwo = new ServiceEntry()
|
||||
{
|
||||
Service = new AgentService()
|
||||
{
|
||||
Service = serviceName,
|
||||
Address = "localhost",
|
||||
Port = serviceTwoPort,
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Tags = new string[0]
|
||||
},
|
||||
};
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
GlobalConfiguration = new FileGlobalConfiguration()
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = consulPort
|
||||
},
|
||||
LoadBalancerOptions = new FileLoadBalancerOptions { Type = "LeastConnection" },
|
||||
DownstreamScheme = "http"
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenProductServiceOneIsRunning(downstreamServiceOneUrl, 200))
|
||||
.And(x => x.GivenProductServiceTwoIsRunning(downstreamServiceTwoUrl, 200))
|
||||
.And(x => x.GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
|
||||
.And(x => x.GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimes($"/{serviceName}/", 50))
|
||||
.Then(x => x.ThenTheTwoServicesShouldHaveBeenCalledTimes(50))
|
||||
.And(x => x.ThenBothServicesCalledRealisticAmountOfTimes(24, 26))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_token_to_make_request_to_consul()
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
|
||||
_internalRepo
|
||||
.Setup(x => x.Get())
|
||||
.Returns(new OkResponse<IInternalConfiguration>(new InternalConfiguration(new List<ReRoute>(), "", new ServiceProviderConfigurationBuilder().Build(), "")));
|
||||
.Returns(new OkResponse<IInternalConfiguration>(new InternalConfiguration(new List<ReRoute>(), "", new ServiceProviderConfigurationBuilder().Build(), "", It.IsAny<LoadBalancerOptions>(), It.IsAny<string>(), It.IsAny<QoSOptions>(), It.IsAny<HttpHandlerOptions>())));
|
||||
|
||||
_repo = new ConsulFileConfigurationRepository(_cache.Object, _internalRepo.Object, _factory.Object, _loggerFactory.Object);
|
||||
}
|
||||
@ -140,7 +140,10 @@ namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
_internalRepo
|
||||
.Setup(x => x.Get())
|
||||
.Returns(new OkResponse<IInternalConfiguration>(new InternalConfiguration(new List<ReRoute>(), "", new ServiceProviderConfigurationBuilder().WithConfigurationKey(key).Build(), "")));
|
||||
.Returns(new OkResponse<IInternalConfiguration>(new InternalConfiguration(new List<ReRoute>(), "",
|
||||
new ServiceProviderConfigurationBuilder().WithConfigurationKey(key).Build(), "",
|
||||
new LoadBalancerOptionsBuilder().Build(), "", new QoSOptionsBuilder().Build(),
|
||||
new HttpHandlerOptionsBuilder().Build())));
|
||||
|
||||
_repo = new ConsulFileConfigurationRepository(_cache.Object, _internalRepo.Object, _factory.Object, _loggerFactory.Object);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
var fileConfig = new FileConfiguration();
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
|
||||
var config = new InternalConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, "asdf");
|
||||
var config = new InternalConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, "asdf", new LoadBalancerOptionsBuilder().Build(), "", new QoSOptionsBuilder().Build(), new HttpHandlerOptionsBuilder().Build());
|
||||
|
||||
this.Given(x => GivenTheFollowingConfiguration(fileConfig))
|
||||
.And(x => GivenTheRepoReturns(new OkResponse()))
|
||||
|
@ -86,7 +86,7 @@
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithReRouteKey("CookieStickySessions:sessionid")
|
||||
.WithLoadBalancerKey("CookieStickySessions:sessionid")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -199,7 +199,7 @@
|
||||
.WithDownstreamScheme("http")
|
||||
.WithUpstreamHttpMethod(new List<string>() {"Get"})
|
||||
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() {new DownstreamHostAndPort("localhost", 51878)})
|
||||
.WithReRouteKey("/laura|Get")
|
||||
.WithLoadBalancerKey("/laura|Get")
|
||||
.Build();
|
||||
|
||||
var lauraReRoute = new ReRouteBuilder()
|
||||
@ -218,7 +218,7 @@
|
||||
.WithDownstreamScheme("http")
|
||||
.WithUpstreamHttpMethod(new List<string>() { "Get" })
|
||||
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() { new DownstreamHostAndPort("localhost", 51878) })
|
||||
.WithReRouteKey("/tom|Get")
|
||||
.WithLoadBalancerKey("/tom|Get")
|
||||
.Build();
|
||||
|
||||
var tomReRoute = new ReRouteBuilder()
|
||||
@ -361,7 +361,6 @@
|
||||
.Build();
|
||||
|
||||
var serviceOptions = new ReRouteOptionsBuilder()
|
||||
.WithIsQos(true)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -410,7 +409,7 @@
|
||||
.WithDownstreamPathTemplate("/products/{productId}")
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -462,7 +461,7 @@
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithDelegatingHandlers(handlers)
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -507,7 +506,7 @@
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithUseServiceDiscovery(true)
|
||||
.WithServiceName("ProductService")
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -558,7 +557,7 @@
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithUseServiceDiscovery(false)
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -601,7 +600,7 @@
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -646,7 +645,7 @@
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithRequestIdKey("blahhhh")
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||
@ -741,7 +740,7 @@
|
||||
{
|
||||
new ClaimToThing("CustomerId", "CustomerId", "", 0),
|
||||
})
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
var expected = new List<ReRoute>
|
||||
@ -784,7 +783,7 @@
|
||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithAuthenticationOptions(authenticationOptions)
|
||||
.WithReRouteKey("/api/products/{productId}|Get")
|
||||
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||
.Build();
|
||||
|
||||
var expected = new List<ReRoute>
|
||||
@ -942,16 +941,15 @@
|
||||
private void GivenTheQosOptionsCreatorReturns(QoSOptions qosOptions)
|
||||
{
|
||||
_qosOptionsCreator
|
||||
.Setup(x => x.Create(_fileConfiguration.ReRoutes[0]))
|
||||
.Setup(x => x.Create(_fileConfiguration.ReRoutes[0].QoSOptions, It.IsAny<string>(), It.IsAny<string[]>()))
|
||||
.Returns(qosOptions);
|
||||
}
|
||||
|
||||
private void ThenTheQosOptionsAre(QoSOptions qosOptions)
|
||||
{
|
||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
|
||||
|
||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
|
||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
|
||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
|
||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
|
||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
|
||||
}
|
||||
|
||||
private void ThenTheServiceProviderCreatorIsCalledCorrectly()
|
||||
@ -992,13 +990,13 @@
|
||||
|
||||
private void GivenTheFollowingHttpHandlerOptionsAreReturned(HttpHandlerOptions httpHandlerOptions)
|
||||
{
|
||||
_httpHandlerOptionsCreator.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||
_httpHandlerOptionsCreator.Setup(x => x.Create(It.IsAny<FileHttpHandlerOptions>()))
|
||||
.Returns(httpHandlerOptions);
|
||||
}
|
||||
|
||||
private void ThenTheHttpHandlerOptionsCreatorIsCalledCorrectly()
|
||||
{
|
||||
_httpHandlerOptionsCreator.Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once());
|
||||
_httpHandlerOptionsCreator.Verify(x => x.Create(_fileConfiguration.ReRoutes[0].HttpHandlerOptions), Times.Once());
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamAddresses()
|
||||
|
@ -103,7 +103,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
|
||||
private void WhenICreateHttpHandlerOptions()
|
||||
{
|
||||
_httpHandlerOptions = _httpHandlerOptionsCreator.Create(_fileReRoute);
|
||||
_httpHandlerOptions = _httpHandlerOptionsCreator.Create(_fileReRoute.HttpHandlerOptions);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingOptionsReturned(HttpHandlerOptions expected)
|
||||
|
@ -105,6 +105,10 @@ namespace Ocelot.UnitTests.Configuration
|
||||
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
|
||||
|
||||
public string RequestId {get;}
|
||||
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||
public string DownstreamScheme { get; }
|
||||
public QoSOptions QoSOptions { get; }
|
||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Create(_fileReRoute);
|
||||
_result = _creator.Create(_fileReRoute.QoSOptions);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(QoSOptions expected)
|
||||
|
@ -29,11 +29,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
EnableRateLimiting = true
|
||||
},
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
TimeoutValue = 1
|
||||
},
|
||||
AuthenticationOptions = new FileAuthenticationOptions()
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
@ -52,7 +47,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.WithIsAuthenticated(true)
|
||||
.WithIsAuthorised(true)
|
||||
.WithIsCached(true)
|
||||
.WithIsQos(true)
|
||||
.WithRateLimiting(true)
|
||||
.Build();
|
||||
|
||||
@ -76,7 +70,6 @@ namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
_result.IsAuthenticated.ShouldBe(expected.IsAuthenticated);
|
||||
_result.IsAuthorised.ShouldBe(expected.IsAuthorised);
|
||||
_result.IsQos.ShouldBe(expected.IsQos);
|
||||
_result.IsCached.ShouldBe(expected.IsCached);
|
||||
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
|
||||
}
|
||||
|
@ -0,0 +1,194 @@
|
||||
using Ocelot.DownstreamRouteFinder.Finder;
|
||||
using Xunit;
|
||||
using Shouldly;
|
||||
using Ocelot.Configuration;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||
{
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Responses;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class DownstreamRouteCreatorTests
|
||||
{
|
||||
private readonly DownstreamRouteCreator _creator;
|
||||
private readonly QoSOptions _qoSOptions;
|
||||
private readonly HttpHandlerOptions _handlerOptions;
|
||||
private readonly LoadBalancerOptions _loadBalancerOptions;
|
||||
private Response<DownstreamRoute> _result;
|
||||
private string _upstreamHost;
|
||||
private string _upstreamUrlPath;
|
||||
private string _upstreamHttpMethod;
|
||||
private IInternalConfiguration _configuration;
|
||||
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
||||
|
||||
public DownstreamRouteCreatorTests()
|
||||
{
|
||||
_qosOptionsCreator = new Mock<IQoSOptionsCreator>();
|
||||
_qoSOptions = new QoSOptionsBuilder().Build();
|
||||
_handlerOptions = new HttpHandlerOptionsBuilder().Build();
|
||||
_loadBalancerOptions = new LoadBalancerOptionsBuilder().WithType(nameof(NoLoadBalancer)).Build();
|
||||
_qosOptionsCreator
|
||||
.Setup(x => x.Create(It.IsAny<QoSOptions>(), It.IsAny<string>(), It.IsAny<string[]>()))
|
||||
.Returns(_qoSOptions);
|
||||
_creator = new DownstreamRouteCreator(_qosOptionsCreator.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_route()
|
||||
{
|
||||
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||
|
||||
this.Given(_ => GivenTheConfiguration(configuration))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheDownstreamRouteIsCreated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_route_with_no_path()
|
||||
{
|
||||
var upstreamUrlPath = "/auth/";
|
||||
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||
|
||||
this.Given(_ => GivenTheConfiguration(configuration, upstreamUrlPath))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheDownstreamPathIsForwardSlash())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_route_and_remove_query_string()
|
||||
{
|
||||
var upstreamUrlPath = "/auth/test?test=1&best=2";
|
||||
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||
|
||||
this.Given(_ => GivenTheConfiguration(configuration, upstreamUrlPath))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheQueryStringIsRemoved())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_route_for_sticky_sessions()
|
||||
{
|
||||
var loadBalancerOptions = new LoadBalancerOptionsBuilder().WithType(nameof(CookieStickySessions)).WithKey("boom").WithExpiryInMs(1).Build();
|
||||
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||
|
||||
this.Given(_ => GivenTheConfiguration(configuration))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheStickySessionLoadBalancerIsUsed(loadBalancerOptions))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_route_with_qos()
|
||||
{
|
||||
var qoSOptions = new QoSOptionsBuilder()
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.WithTimeoutValue(1)
|
||||
.Build();
|
||||
|
||||
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", qoSOptions, _handlerOptions);
|
||||
|
||||
this.Given(_ => GivenTheConfiguration(configuration))
|
||||
.And(_ => GivenTheQosCreatorReturns(qoSOptions))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheQosOptionsAreSet(qoSOptions))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_route_with_handler_options()
|
||||
{
|
||||
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||
|
||||
this.Given(_ => GivenTheConfiguration(configuration))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheHandlerOptionsAreSet())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheQosCreatorReturns(QoSOptions options)
|
||||
{
|
||||
_qosOptionsCreator
|
||||
.Setup(x => x.Create(It.IsAny<QoSOptions>(), It.IsAny<string>(), It.IsAny<string[]>()))
|
||||
.Returns(options);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamRouteIsCreated()
|
||||
{
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("/test");
|
||||
_result.Data.ReRoute.UpstreamHttpMethod[0].ShouldBe(HttpMethod.Get);
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].ServiceName.ShouldBe("auth");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe("/auth/test|GET");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].UseServiceDiscovery.ShouldBeTrue();
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].HttpHandlerOptions.ShouldNotBeNull();
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].QosOptions.ShouldNotBeNull();
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamScheme.ShouldBe("http");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerOptions.Type.ShouldBe(nameof(NoLoadBalancer));
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].HttpHandlerOptions.ShouldBe(_handlerOptions);
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].QosOptions.ShouldBe(_qoSOptions);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamPathIsForwardSlash()
|
||||
{
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("/");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].ServiceName.ShouldBe("auth");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe("/auth/|GET");
|
||||
}
|
||||
|
||||
private void ThenTheQueryStringIsRemoved()
|
||||
{
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("/test");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].ServiceName.ShouldBe("auth");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe("/auth/test|GET");
|
||||
}
|
||||
|
||||
private void ThenTheStickySessionLoadBalancerIsUsed(LoadBalancerOptions expected)
|
||||
{
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe($"{nameof(CookieStickySessions)}:boom");
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerOptions.Type.ShouldBe(nameof(CookieStickySessions));
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerOptions.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void ThenTheQosOptionsAreSet(QoSOptions expected)
|
||||
{
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].QosOptions.ShouldBe(expected);
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].QosOptions.UseQos.ShouldBeTrue();
|
||||
_qosOptionsCreator
|
||||
.Verify(x => x.Create(expected, _upstreamUrlPath, It.IsAny<string[]>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheConfiguration(IInternalConfiguration config)
|
||||
{
|
||||
_upstreamHost = "doesnt matter";
|
||||
_upstreamUrlPath = "/auth/test";
|
||||
_upstreamHttpMethod = "GET";
|
||||
_configuration = config;
|
||||
}
|
||||
|
||||
private void GivenTheConfiguration(IInternalConfiguration config, string upstreamUrlPath)
|
||||
{
|
||||
_upstreamHost = "doesnt matter";
|
||||
_upstreamUrlPath = upstreamUrlPath;
|
||||
_upstreamHttpMethod = "GET";
|
||||
_configuration = config;
|
||||
}
|
||||
|
||||
private void ThenTheHandlerOptionsAreSet()
|
||||
{
|
||||
_result.Data.ReRoute.DownstreamReRoute[0].HttpHandlerOptions.ShouldBe(_handlerOptions);
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,8 @@
|
||||
|
||||
public class DownstreamRouteFinderMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IDownstreamRouteFinder> _finder;
|
||||
private readonly Mock<IDownstreamRouteProvider> _finder;
|
||||
private readonly Mock<IDownstreamRouteProviderFactory> _factory;
|
||||
private readonly Mock<IInternalConfigurationRepository> _repo;
|
||||
private Response<DownstreamRoute> _downstreamRoute;
|
||||
private IInternalConfiguration _config;
|
||||
@ -35,20 +36,22 @@
|
||||
public DownstreamRouteFinderMiddlewareTests()
|
||||
{
|
||||
_repo = new Mock<IInternalConfigurationRepository>();
|
||||
_finder = new Mock<IDownstreamRouteFinder>();
|
||||
_finder = new Mock<IDownstreamRouteProvider>();
|
||||
_factory = new Mock<IDownstreamRouteProviderFactory>();
|
||||
_factory.Setup(x => x.Get(It.IsAny<IInternalConfiguration>())).Returns(_finder.Object);
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_multiplexer = new Mock<IMultiplexer>();
|
||||
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _repo.Object, _multiplexer.Object);
|
||||
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _factory.Object, _repo.Object, _multiplexer.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_scoped_data_repository_correctly()
|
||||
{
|
||||
var config = new InternalConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "");
|
||||
var config = new InternalConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "", new LoadBalancerOptionsBuilder().Build(), "", new QoSOptionsBuilder().Build(), new HttpHandlerOptionsBuilder().Build());
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
@ -76,23 +79,21 @@
|
||||
private void GivenTheFollowingConfig(IInternalConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_repo
|
||||
.Setup(x => x.Get())
|
||||
.Returns(new OkResponse<IInternalConfiguration>(_config));
|
||||
_downstreamContext.Configuration = config;
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||
_finder
|
||||
.Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IInternalConfiguration>(), It.IsAny<string>()))
|
||||
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IInternalConfiguration>(), It.IsAny<string>()))
|
||||
.Returns(_downstreamRoute);
|
||||
}
|
||||
|
||||
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues.ShouldBe(_downstreamRoute.Data.TemplatePlaceholderNameAndValues);
|
||||
_downstreamContext.ServiceProviderConfiguration.ShouldBe(_config.ServiceProviderConfiguration);
|
||||
_downstreamContext.Configuration.ServiceProviderConfiguration.ShouldBe(_config.ServiceProviderConfiguration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||
{
|
||||
public class DownstreamRouteFinderTests
|
||||
{
|
||||
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
||||
private readonly IDownstreamRouteProvider _downstreamRouteFinder;
|
||||
private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher;
|
||||
private readonly Mock<IPlaceholderNameAndValueFinder> _finder;
|
||||
private string _upstreamUrlPath;
|
||||
@ -709,7 +709,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
|
||||
{
|
||||
_reRoutesConfig = reRoutesConfig;
|
||||
_config = new InternalConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, "");
|
||||
_config = new InternalConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, "", new LoadBalancerOptionsBuilder().Build(), "", new QoSOptionsBuilder().Build(), new HttpHandlerOptionsBuilder().Build());
|
||||
}
|
||||
|
||||
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
|
||||
@ -719,7 +719,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||
|
||||
private void WhenICallTheFinder()
|
||||
{
|
||||
_result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod, _config, _upstreamHost);
|
||||
_result = _downstreamRouteFinder.Get(_upstreamUrlPath, _upstreamHttpMethod, _config, _upstreamHost);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(DownstreamRoute expected)
|
||||
|
@ -0,0 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.Finder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||
{
|
||||
using Ocelot.Configuration.Creator;
|
||||
|
||||
public class DownstreamRouteProviderFactoryTests
|
||||
{
|
||||
private readonly DownstreamRouteProviderFactory _factory;
|
||||
private IInternalConfiguration _config;
|
||||
private IDownstreamRouteProvider _result;
|
||||
|
||||
public DownstreamRouteProviderFactoryTests()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
|
||||
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
||||
services.AddSingleton<IQoSOptionsCreator, QoSOptionsCreator>();
|
||||
services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>();
|
||||
services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>();
|
||||
var provider = services.BuildServiceProvider();
|
||||
_factory = new DownstreamRouteProviderFactory(provider);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_downstream_route_finder()
|
||||
{
|
||||
var reRoutes = new List<ReRoute>
|
||||
{
|
||||
new ReRouteBuilder().Build()
|
||||
};
|
||||
|
||||
this.Given(_ => GivenTheReRoutes(reRoutes))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_downstream_route_finder_as_no_service_discovery()
|
||||
{
|
||||
var spConfig = new ServiceProviderConfigurationBuilder().Build();
|
||||
var reRoutes = new List<ReRoute>
|
||||
{
|
||||
};
|
||||
|
||||
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_downstream_route_creator()
|
||||
{
|
||||
var spConfig = new ServiceProviderConfigurationBuilder().WithHost("test").WithPort(50).Build();
|
||||
var reRoutes = new List<ReRoute>
|
||||
{
|
||||
};
|
||||
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheResultShouldBe<T>()
|
||||
{
|
||||
_result.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void WhenIGet()
|
||||
{
|
||||
_result = _factory.Get(_config);
|
||||
}
|
||||
|
||||
private void GivenTheReRoutes(List<ReRoute> reRoutes)
|
||||
{
|
||||
_config = new InternalConfiguration(reRoutes, "", null, "", new LoadBalancerOptionsBuilder().Build(), "", new QoSOptionsBuilder().Build(), new HttpHandlerOptionsBuilder().Build());
|
||||
}
|
||||
|
||||
private void GivenTheReRoutes(List<ReRoute> reRoutes, ServiceProviderConfiguration config)
|
||||
{
|
||||
_config = new InternalConfiguration(reRoutes, "", config, "", new LoadBalancerOptionsBuilder().Build(), "", new QoSOptionsBuilder().Build(), new HttpHandlerOptionsBuilder().Build());
|
||||
}
|
||||
}
|
||||
}
|
@ -193,7 +193,8 @@
|
||||
|
||||
private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
_downstreamContext.ServiceProviderConfiguration = config;
|
||||
var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null);
|
||||
_downstreamContext.Configuration = configuration;
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
|
@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.Errors
|
||||
[Fact]
|
||||
public void NoDownstreamException()
|
||||
{
|
||||
var config = new InternalConfiguration(null, null, null, null);
|
||||
var config = new InternalConfiguration(null, null, null, null, null, null, null, null);
|
||||
|
||||
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||
.And(_ => GivenTheConfigurationIs(config))
|
||||
@ -64,7 +64,7 @@ namespace Ocelot.UnitTests.Errors
|
||||
[Fact]
|
||||
public void DownstreamException()
|
||||
{
|
||||
var config = new InternalConfiguration(null, null, null, null);
|
||||
var config = new InternalConfiguration(null, null, null, null, null, null, null, null);
|
||||
|
||||
this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
|
||||
.And(_ => GivenTheConfigurationIs(config))
|
||||
@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Errors
|
||||
[Fact]
|
||||
public void ShouldSetRequestId()
|
||||
{
|
||||
var config = new InternalConfiguration(null, null, null, "requestidkey");
|
||||
var config = new InternalConfiguration(null, null, null, "requestidkey", null, null, null, null);
|
||||
|
||||
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||
.And(_ => GivenTheConfigurationIs(config))
|
||||
@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.Errors
|
||||
[Fact]
|
||||
public void ShouldSetAspDotNetRequestId()
|
||||
{
|
||||
var config = new InternalConfiguration(null, null, null, null);
|
||||
var config = new InternalConfiguration(null, null, null, null, null, null, null, null);
|
||||
|
||||
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||
.And(_ => GivenTheConfigurationIs(config))
|
||||
|
@ -33,7 +33,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
public void should_store_load_balancer_on_first_request()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithReRouteKey("test")
|
||||
.WithLoadBalancerKey("test")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
@ -46,7 +46,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
||||
.WithReRouteKey("test")
|
||||
.WithLoadBalancerKey("test")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
@ -60,12 +60,12 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
||||
.WithReRouteKey("test")
|
||||
.WithLoadBalancerKey("test")
|
||||
.Build();
|
||||
|
||||
var reRouteTwo = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeRoundRobinLoadBalancer", "", 0))
|
||||
.WithReRouteKey("testtwo")
|
||||
.WithLoadBalancerKey("testtwo")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
@ -92,12 +92,12 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
||||
.WithReRouteKey("test")
|
||||
.WithLoadBalancerKey("test")
|
||||
.Build();
|
||||
|
||||
var reRouteTwo = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("LeastConnection", "", 0))
|
||||
.WithReRouteKey("test")
|
||||
.WithLoadBalancerKey("test")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||
|
@ -117,7 +117,8 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_downstreamContext.ServiceProviderConfiguration = config;
|
||||
var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null);
|
||||
_downstreamContext.Configuration = configuration;
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||
|
@ -38,14 +38,21 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_follow_ordering_add_specifics()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
"FakeDelegatingHandlerTwo"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
@ -67,7 +74,14 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_follow_ordering_order_specifics_and_globals()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
@ -75,7 +89,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
"FakeDelegatingHandler",
|
||||
"FakeDelegatingHandlerFour"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
@ -97,14 +111,21 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_follow_ordering_order_specifics()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandlerTwo",
|
||||
"FakeDelegatingHandler"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
@ -126,13 +147,20 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_follow_ordering_order_and_only_add_specifics_in_config()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
@ -153,9 +181,16 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_follow_ordering_dont_add_specifics()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
@ -175,14 +210,18 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_apply_re_route_specific()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
"FakeDelegatingHandlerTwo"
|
||||
})
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
@ -197,8 +236,15 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_all_from_all_routes_provider_and_qos()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithLoadBalancerKey("").Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
@ -213,8 +259,12 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_return_provider_with_no_delegates()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(false)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithLoadBalancerKey("").Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheServiceProviderReturnsNothing())
|
||||
@ -226,8 +276,15 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_return_provider_with_qos_delegate()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithLoadBalancerKey("").Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||
@ -241,8 +298,15 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_return_error()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithLoadBalancerKey("").Build();
|
||||
|
||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||
.And(x => GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
|
||||
|
@ -46,10 +46,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_build_http_client()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
@ -63,10 +66,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_log_if_ignoring_ssl_errors()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.WithDangerousAcceptAnyServerCertificateValidator(true)
|
||||
.Build();
|
||||
@ -82,10 +88,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_call_delegating_handlers_in_order()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
@ -110,10 +119,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_re_use_cookies_from_container()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
@ -142,10 +154,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
HttpMethod method = new HttpMethod(verb);
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
|
@ -47,10 +47,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_call_request_correctly()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
@ -70,10 +73,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_call_request_unable_to_complete_request()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
@ -92,10 +98,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void http_client_request_times_out()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsQos(false)
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||
.WithReRouteKey("")
|
||||
.WithLoadBalancerKey("")
|
||||
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())
|
||||
.Build();
|
||||
|
||||
|
@ -31,9 +31,12 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_return_no_qos_provider()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithUpstreamHttpMethod(new List<string> { "get" })
|
||||
.WithIsQos(false)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
@ -53,7 +56,6 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "get" })
|
||||
.WithIsQos(true)
|
||||
.WithQosOptions(qosOptions)
|
||||
.Build();
|
||||
|
||||
|
@ -26,7 +26,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_store_qos_provider_on_first_request()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithQosKey("test").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithKey("test")
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||
.Then(x => x.ThenItIsAdded())
|
||||
@ -36,7 +42,13 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_not_store_qos_provider_on_first_request()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithQosKey("test").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithKey("test")
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
||||
@ -47,8 +59,21 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_store_qos_providers_by_key()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithQosKey("test").Build();
|
||||
var reRouteTwo = new DownstreamReRouteBuilder().WithQosKey("testTwo").Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.WithKey("test")
|
||||
.Build();
|
||||
|
||||
var qosOptionsTwo = new QoSOptionsBuilder()
|
||||
.WithKey("testTwo")
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.Build();
|
||||
|
||||
var reRouteTwo = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptionsTwo)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||
.And(x => x.GivenThereIsAQoSProvider(reRouteTwo, new FakePollyQoSProvider()))
|
||||
@ -62,7 +87,12 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_return_error_if_no_qos_provider_with_key()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().Build();
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.Build();
|
||||
|
||||
this.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
||||
.Then(x => x.ThenAnErrorIsReturned())
|
||||
@ -72,9 +102,24 @@ namespace Ocelot.UnitTests.Requester
|
||||
[Fact]
|
||||
public void should_get_new_qos_provider_if_reroute_qos_provider_has_changed()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder().WithQosKey("test").Build();
|
||||
var useQoSOptions = new QoSOptionsBuilder()
|
||||
.WithTimeoutValue(1)
|
||||
.WithKey("test")
|
||||
.WithDurationOfBreak(1)
|
||||
.WithExceptionsAllowedBeforeBreaking(1)
|
||||
.Build();
|
||||
|
||||
var reRouteTwo = new DownstreamReRouteBuilder().WithQosKey("test").WithIsQos(true).Build();
|
||||
var dontUseQoSOptions = new QoSOptionsBuilder()
|
||||
.WithKey("test")
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(dontUseQoSOptions)
|
||||
.Build();
|
||||
|
||||
var reRouteTwo = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(useQoSOptions)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
||||
|
Loading…
x
Reference in New Issue
Block a user