mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:42:50 +08:00
commit
6f2eaa412f
@ -51,7 +51,7 @@ A quick list of Ocelot's capabilities for more information see the [documentatio
|
|||||||
* Headers / Query String / Claims Transformation
|
* Headers / Query String / Claims Transformation
|
||||||
* Custom Middleware / Delegating Handlers
|
* Custom Middleware / Delegating Handlers
|
||||||
* Configuration / Administration REST API
|
* Configuration / Administration REST API
|
||||||
* Platform / Cloud agnostic
|
* Platform / Cloud Agnostic
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
|
@ -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
|
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!).
|
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
|
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
|
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.
|
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
|
public class DownstreamReRouteBuilder
|
||||||
{
|
{
|
||||||
private AuthenticationOptions _authenticationOptions;
|
private AuthenticationOptions _authenticationOptions;
|
||||||
private string _reRouteKey;
|
private string _loadBalancerKey;
|
||||||
private string _downstreamPathTemplate;
|
private string _downstreamPathTemplate;
|
||||||
private string _upstreamTemplate;
|
private string _upstreamTemplate;
|
||||||
private UpstreamPathTemplate _upstreamTemplatePattern;
|
private UpstreamPathTemplate _upstreamTemplatePattern;
|
||||||
@ -25,7 +25,6 @@ namespace Ocelot.Configuration.Builder
|
|||||||
private CacheOptions _fileCacheOptions;
|
private CacheOptions _fileCacheOptions;
|
||||||
private string _downstreamScheme;
|
private string _downstreamScheme;
|
||||||
private LoadBalancerOptions _loadBalancerOptions;
|
private LoadBalancerOptions _loadBalancerOptions;
|
||||||
private bool _useQos;
|
|
||||||
private QoSOptions _qosOptions;
|
private QoSOptions _qosOptions;
|
||||||
private HttpHandlerOptions _httpHandlerOptions;
|
private HttpHandlerOptions _httpHandlerOptions;
|
||||||
private bool _enableRateLimiting;
|
private bool _enableRateLimiting;
|
||||||
@ -41,7 +40,6 @@ namespace Ocelot.Configuration.Builder
|
|||||||
private List<AddHeader> _addHeadersToDownstream;
|
private List<AddHeader> _addHeadersToDownstream;
|
||||||
private List<AddHeader> _addHeadersToUpstream;
|
private List<AddHeader> _addHeadersToUpstream;
|
||||||
private bool _dangerousAcceptAnyServerCertificateValidator;
|
private bool _dangerousAcceptAnyServerCertificateValidator;
|
||||||
private string _qosKey;
|
|
||||||
|
|
||||||
public DownstreamReRouteBuilder()
|
public DownstreamReRouteBuilder()
|
||||||
{
|
{
|
||||||
@ -153,27 +151,15 @@ namespace Ocelot.Configuration.Builder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithIsQos(bool input)
|
|
||||||
{
|
|
||||||
_useQos = input;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithQosOptions(QoSOptions input)
|
public DownstreamReRouteBuilder WithQosOptions(QoSOptions input)
|
||||||
{
|
{
|
||||||
_qosOptions = input;
|
_qosOptions = input;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithReRouteKey(string reRouteKey)
|
public DownstreamReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
|
||||||
{
|
{
|
||||||
_reRouteKey = reRouteKey;
|
_loadBalancerKey = loadBalancerKey;
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithQosKey(string qosKey)
|
|
||||||
{
|
|
||||||
_qosKey = qosKey;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +253,6 @@ namespace Ocelot.Configuration.Builder
|
|||||||
_httpHandlerOptions,
|
_httpHandlerOptions,
|
||||||
_useServiceDiscovery,
|
_useServiceDiscovery,
|
||||||
_enableRateLimiting,
|
_enableRateLimiting,
|
||||||
_useQos,
|
|
||||||
_qosOptions,
|
_qosOptions,
|
||||||
_downstreamScheme,
|
_downstreamScheme,
|
||||||
_requestIdHeaderKey,
|
_requestIdHeaderKey,
|
||||||
@ -283,12 +268,11 @@ namespace Ocelot.Configuration.Builder
|
|||||||
_isAuthorised,
|
_isAuthorised,
|
||||||
_authenticationOptions,
|
_authenticationOptions,
|
||||||
new PathTemplate(_downstreamPathTemplate),
|
new PathTemplate(_downstreamPathTemplate),
|
||||||
_reRouteKey,
|
_loadBalancerKey,
|
||||||
_delegatingHandlers,
|
_delegatingHandlers,
|
||||||
_addHeadersToDownstream,
|
_addHeadersToDownstream,
|
||||||
_addHeadersToUpstream,
|
_addHeadersToUpstream,
|
||||||
_dangerousAcceptAnyServerCertificateValidator,
|
_dangerousAcceptAnyServerCertificateValidator);
|
||||||
_qosKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
private int _timeoutValue;
|
private int _timeoutValue;
|
||||||
|
|
||||||
|
private string _key;
|
||||||
|
|
||||||
public QoSOptionsBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
|
public QoSOptionsBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
|
||||||
{
|
{
|
||||||
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
||||||
@ -26,9 +28,15 @@
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QoSOptionsBuilder WithKey(string input)
|
||||||
|
{
|
||||||
|
_key = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public QoSOptions Build()
|
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 _isAuthenticated;
|
||||||
private bool _isAuthorised;
|
private bool _isAuthorised;
|
||||||
private bool _isCached;
|
private bool _isCached;
|
||||||
private bool _isQoS;
|
|
||||||
private bool _enableRateLimiting;
|
private bool _enableRateLimiting;
|
||||||
|
|
||||||
public ReRouteOptionsBuilder WithIsCached(bool isCached)
|
public ReRouteOptionsBuilder WithIsCached(bool isCached)
|
||||||
@ -26,12 +25,6 @@ namespace Ocelot.Configuration.Builder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReRouteOptionsBuilder WithIsQos(bool isQoS)
|
|
||||||
{
|
|
||||||
_isQoS = isQoS;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
|
public ReRouteOptionsBuilder WithRateLimiting(bool enableRateLimiting)
|
||||||
{
|
{
|
||||||
_enableRateLimiting = enableRateLimiting;
|
_enableRateLimiting = enableRateLimiting;
|
||||||
@ -40,7 +33,7 @@ namespace Ocelot.Configuration.Builder
|
|||||||
|
|
||||||
public ReRouteOptions Build()
|
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 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);
|
return new OkResponse<IInternalConfiguration>(config);
|
||||||
}
|
}
|
||||||
@ -160,8 +174,6 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
var reRouteKey = CreateReRouteKey(fileReRoute);
|
var reRouteKey = CreateReRouteKey(fileReRoute);
|
||||||
|
|
||||||
var qosKey = CreateQosKey(fileReRoute);
|
|
||||||
|
|
||||||
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
|
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
|
||||||
@ -172,19 +184,19 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
|
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 rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
||||||
|
|
||||||
var region = _regionCreator.Create(fileReRoute);
|
var region = _regionCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute);
|
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute.HttpHandlerOptions);
|
||||||
|
|
||||||
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
|
var hAndRs = _headerFAndRCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
|
var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var lbOptions = CreateLoadBalancerOptions(fileReRoute);
|
var lbOptions = CreateLoadBalancerOptions(fileReRoute.LoadBalancerOptions);
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithKey(fileReRoute.Key)
|
.WithKey(fileReRoute.Key)
|
||||||
@ -205,9 +217,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
||||||
.WithLoadBalancerOptions(lbOptions)
|
.WithLoadBalancerOptions(lbOptions)
|
||||||
.WithDownstreamAddresses(downstreamAddresses)
|
.WithDownstreamAddresses(downstreamAddresses)
|
||||||
.WithReRouteKey(reRouteKey)
|
.WithLoadBalancerKey(reRouteKey)
|
||||||
.WithQosKey(qosKey)
|
|
||||||
.WithIsQos(fileReRouteOptions.IsQos)
|
|
||||||
.WithQosOptions(qosOptions)
|
.WithQosOptions(qosOptions)
|
||||||
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
|
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
|
||||||
.WithRateLimitOptions(rateLimitOption)
|
.WithRateLimitOptions(rateLimitOption)
|
||||||
@ -226,9 +236,13 @@ namespace Ocelot.Configuration.Creator
|
|||||||
return reRoute;
|
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)
|
private string CreateReRouteKey(FileReRoute fileReRoute)
|
||||||
@ -238,14 +252,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
|
return $"{nameof(CookieStickySessions)}:{fileReRoute.LoadBalancerOptions.Key}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateQosKey(fileReRoute);
|
return $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,19 @@ namespace Ocelot.Configuration.Creator
|
|||||||
{
|
{
|
||||||
public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator
|
public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator
|
||||||
{
|
{
|
||||||
private IServiceTracer _tracer;
|
private readonly IServiceTracer _tracer;
|
||||||
|
|
||||||
public HttpHandlerOptionsCreator(IServiceTracer tracer)
|
public HttpHandlerOptionsCreator(IServiceTracer tracer)
|
||||||
{
|
{
|
||||||
_tracer = 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,
|
return new HttpHandlerOptions(options.AllowAutoRedirect,
|
||||||
fileReRoute.HttpHandlerOptions.UseCookieContainer, useTracing);
|
options.UseCookieContainer, useTracing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,6 @@ namespace Ocelot.Configuration.Creator
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHttpHandlerOptionsCreator
|
public interface IHttpHandlerOptionsCreator
|
||||||
{
|
{
|
||||||
HttpHandlerOptions Create(FileReRoute fileReRoute);
|
HttpHandlerOptions Create(FileHttpHandlerOptions fileReRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ namespace Ocelot.Configuration.Creator
|
|||||||
{
|
{
|
||||||
public interface IQoSOptionsCreator
|
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
|
namespace Ocelot.Configuration.Creator
|
||||||
{
|
{
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
public class QoSOptionsCreator : IQoSOptionsCreator
|
public class QoSOptionsCreator : IQoSOptionsCreator
|
||||||
{
|
{
|
||||||
public QoSOptions Create(FileReRoute fileReRoute)
|
public QoSOptions Create(FileQoSOptions options)
|
||||||
{
|
{
|
||||||
return new QoSOptionsBuilder()
|
return new QoSOptionsBuilder()
|
||||||
.WithExceptionsAllowedBeforeBreaking(fileReRoute.QoSOptions.ExceptionsAllowedBeforeBreaking)
|
.WithExceptionsAllowedBeforeBreaking(options.ExceptionsAllowedBeforeBreaking)
|
||||||
.WithDurationOfBreak(fileReRoute.QoSOptions.DurationOfBreak)
|
.WithDurationOfBreak(options.DurationOfBreak)
|
||||||
.WithTimeoutValue(fileReRoute.QoSOptions.TimeoutValue)
|
.WithTimeoutValue(options.TimeoutValue)
|
||||||
.Build();
|
.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 isAuthenticated = IsAuthenticated(fileReRoute);
|
||||||
var isAuthorised = IsAuthorised(fileReRoute);
|
var isAuthorised = IsAuthorised(fileReRoute);
|
||||||
var isCached = IsCached(fileReRoute);
|
var isCached = IsCached(fileReRoute);
|
||||||
var isQos = IsQoS(fileReRoute);
|
|
||||||
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
|
var enableRateLimiting = IsEnableRateLimiting(fileReRoute);
|
||||||
|
|
||||||
var options = new ReRouteOptionsBuilder()
|
var options = new ReRouteOptionsBuilder()
|
||||||
.WithIsAuthenticated(isAuthenticated)
|
.WithIsAuthenticated(isAuthenticated)
|
||||||
.WithIsAuthorised(isAuthorised)
|
.WithIsAuthorised(isAuthorised)
|
||||||
.WithIsCached(isCached)
|
.WithIsCached(isCached)
|
||||||
.WithIsQos(isQos)
|
|
||||||
.WithRateLimiting(enableRateLimiting)
|
.WithRateLimiting(enableRateLimiting)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -29,11 +27,6 @@ namespace Ocelot.Configuration.Creator
|
|||||||
return (fileReRoute.RateLimitOptions != null && fileReRoute.RateLimitOptions.EnableRateLimiting) ? true : false;
|
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)
|
private bool IsAuthenticated(FileReRoute fileReRoute)
|
||||||
{
|
{
|
||||||
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.AuthenticationProviderKey);
|
return !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.AuthenticationProviderKey);
|
||||||
|
@ -7,12 +7,12 @@ namespace Ocelot.Configuration.Creator
|
|||||||
{
|
{
|
||||||
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration)
|
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration)
|
||||||
{
|
{
|
||||||
//todo log or return error here dont just default to something that wont work..
|
var port = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||||
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
var host = globalConfiguration?.ServiceDiscoveryProvider?.Host ?? "consul";
|
||||||
|
|
||||||
return new ServiceProviderConfigurationBuilder()
|
return new ServiceProviderConfigurationBuilder()
|
||||||
.WithHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
|
.WithHost(host)
|
||||||
.WithPort(serviceProviderPort)
|
.WithPort(port)
|
||||||
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
|
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
|
||||||
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
|
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
|
||||||
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
|
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
|
||||||
|
@ -16,8 +16,7 @@ namespace Ocelot.Configuration
|
|||||||
HttpHandlerOptions httpHandlerOptions,
|
HttpHandlerOptions httpHandlerOptions,
|
||||||
bool useServiceDiscovery,
|
bool useServiceDiscovery,
|
||||||
bool enableEndpointEndpointRateLimiting,
|
bool enableEndpointEndpointRateLimiting,
|
||||||
bool isQos,
|
QoSOptions qosOptions,
|
||||||
QoSOptions qosOptionsOptions,
|
|
||||||
string downstreamScheme,
|
string downstreamScheme,
|
||||||
string requestIdKey,
|
string requestIdKey,
|
||||||
bool isCached,
|
bool isCached,
|
||||||
@ -36,8 +35,7 @@ namespace Ocelot.Configuration
|
|||||||
List<string> delegatingHandlers,
|
List<string> delegatingHandlers,
|
||||||
List<AddHeader> addHeadersToDownstream,
|
List<AddHeader> addHeadersToDownstream,
|
||||||
List<AddHeader> addHeadersToUpstream,
|
List<AddHeader> addHeadersToUpstream,
|
||||||
bool dangerousAcceptAnyServerCertificateValidator,
|
bool dangerousAcceptAnyServerCertificateValidator)
|
||||||
string qosKey)
|
|
||||||
{
|
{
|
||||||
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||||
AddHeadersToDownstream = addHeadersToDownstream;
|
AddHeadersToDownstream = addHeadersToDownstream;
|
||||||
@ -51,8 +49,7 @@ namespace Ocelot.Configuration
|
|||||||
HttpHandlerOptions = httpHandlerOptions;
|
HttpHandlerOptions = httpHandlerOptions;
|
||||||
UseServiceDiscovery = useServiceDiscovery;
|
UseServiceDiscovery = useServiceDiscovery;
|
||||||
EnableEndpointEndpointRateLimiting = enableEndpointEndpointRateLimiting;
|
EnableEndpointEndpointRateLimiting = enableEndpointEndpointRateLimiting;
|
||||||
IsQos = isQos;
|
QosOptions = qosOptions;
|
||||||
QosOptionsOptions = qosOptionsOptions;
|
|
||||||
DownstreamScheme = downstreamScheme;
|
DownstreamScheme = downstreamScheme;
|
||||||
RequestIdKey = requestIdKey;
|
RequestIdKey = requestIdKey;
|
||||||
IsCached = isCached;
|
IsCached = isCached;
|
||||||
@ -69,10 +66,8 @@ namespace Ocelot.Configuration
|
|||||||
DownstreamPathTemplate = downstreamPathTemplate;
|
DownstreamPathTemplate = downstreamPathTemplate;
|
||||||
LoadBalancerKey = loadBalancerKey;
|
LoadBalancerKey = loadBalancerKey;
|
||||||
AddHeadersToUpstream = addHeadersToUpstream;
|
AddHeadersToUpstream = addHeadersToUpstream;
|
||||||
QosKey = qosKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string QosKey { get; }
|
|
||||||
public string Key { get; }
|
public string Key { get; }
|
||||||
public PathTemplate UpstreamPathTemplate { get; }
|
public PathTemplate UpstreamPathTemplate { get; }
|
||||||
public List<HeaderFindAndReplace> UpstreamHeadersFindAndReplace { get; }
|
public List<HeaderFindAndReplace> UpstreamHeadersFindAndReplace { get; }
|
||||||
@ -82,8 +77,7 @@ namespace Ocelot.Configuration
|
|||||||
public HttpHandlerOptions HttpHandlerOptions { get; }
|
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||||
public bool UseServiceDiscovery { get; }
|
public bool UseServiceDiscovery { get; }
|
||||||
public bool EnableEndpointEndpointRateLimiting { get; }
|
public bool EnableEndpointEndpointRateLimiting { get; }
|
||||||
public bool IsQos { get; }
|
public QoSOptions QosOptions { get; }
|
||||||
public QoSOptions QosOptionsOptions { get; }
|
|
||||||
public string DownstreamScheme { get; }
|
public string DownstreamScheme { get; }
|
||||||
public string RequestIdKey { get; }
|
public string RequestIdKey { get; }
|
||||||
public bool IsCached { get; }
|
public bool IsCached { get; }
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
{
|
{
|
||||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider();
|
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider();
|
||||||
RateLimitOptions = new FileRateLimitOptions();
|
RateLimitOptions = new FileRateLimitOptions();
|
||||||
|
LoadBalancerOptions = new FileLoadBalancerOptions();
|
||||||
|
QoSOptions = new FileQoSOptions();
|
||||||
|
HttpHandlerOptions = new FileHttpHandlerOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RequestIdKey { get; set; }
|
public string RequestIdKey { get; set; }
|
||||||
@ -14,6 +17,14 @@
|
|||||||
|
|
||||||
public FileRateLimitOptions RateLimitOptions { get; set; }
|
public FileRateLimitOptions RateLimitOptions { get; set; }
|
||||||
|
|
||||||
|
public FileQoSOptions QoSOptions { get; set; }
|
||||||
|
|
||||||
public string BaseUrl { 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
|
public interface IInternalConfiguration
|
||||||
{
|
{
|
||||||
List<ReRoute> ReRoutes { get; }
|
List<ReRoute> ReRoutes { get; }
|
||||||
|
|
||||||
string AdministrationPath {get;}
|
string AdministrationPath {get;}
|
||||||
|
|
||||||
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
||||||
|
|
||||||
string RequestId {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 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;
|
ReRoutes = reRoutes;
|
||||||
AdministrationPath = administrationPath;
|
AdministrationPath = administrationPath;
|
||||||
ServiceProviderConfiguration = serviceProviderConfiguration;
|
ServiceProviderConfiguration = serviceProviderConfiguration;
|
||||||
RequestId = requestId;
|
RequestId = requestId;
|
||||||
|
LoadBalancerOptions = loadBalancerOptions;
|
||||||
|
DownstreamScheme = downstreamScheme;
|
||||||
|
QoSOptions = qoSOptions;
|
||||||
|
HttpHandlerOptions = httpHandlerOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ReRoute> ReRoutes { get; }
|
public List<ReRoute> ReRoutes { get; }
|
||||||
public string AdministrationPath {get;}
|
public string AdministrationPath {get;}
|
||||||
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
||||||
public string RequestId {get;}
|
public string RequestId {get;}
|
||||||
|
public LoadBalancerOptions LoadBalancerOptions { get; }
|
||||||
|
public string DownstreamScheme { get; }
|
||||||
|
public QoSOptions QoSOptions { get; }
|
||||||
|
public HttpHandlerOptions HttpHandlerOptions { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
using Ocelot.LoadBalancer.LoadBalancers;
|
||||||
|
|
||||||
namespace Ocelot.Configuration
|
namespace Ocelot.Configuration
|
||||||
{
|
{
|
||||||
public class LoadBalancerOptions
|
public class LoadBalancerOptions
|
||||||
{
|
{
|
||||||
public LoadBalancerOptions(string type, string key, int expiryInMs)
|
public LoadBalancerOptions(string type, string key, int expiryInMs)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type ?? nameof(NoLoadBalancer);
|
||||||
Key = key;
|
Key = key;
|
||||||
ExpiryInMs = expiryInMs;
|
ExpiryInMs = expiryInMs;
|
||||||
}
|
}
|
||||||
|
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 exceptionsAllowedBeforeBreaking,
|
||||||
int durationofBreak,
|
int durationofBreak,
|
||||||
int timeoutValue,
|
int timeoutValue,
|
||||||
|
string key,
|
||||||
TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
|
TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
|
||||||
{
|
{
|
||||||
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
|
||||||
DurationOfBreak = durationofBreak;
|
DurationOfBreak = durationofBreak;
|
||||||
TimeoutValue = timeoutValue;
|
TimeoutValue = timeoutValue;
|
||||||
TimeoutStrategy = timeoutStrategy;
|
TimeoutStrategy = timeoutStrategy;
|
||||||
|
Key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExceptionsAllowedBeforeBreaking { get; }
|
public int ExceptionsAllowedBeforeBreaking { get; }
|
||||||
@ -23,5 +25,8 @@ namespace Ocelot.Configuration
|
|||||||
public int TimeoutValue { get; }
|
public int TimeoutValue { get; }
|
||||||
|
|
||||||
public TimeoutStrategy TimeoutStrategy { 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 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;
|
IsAuthenticated = isAuthenticated;
|
||||||
IsAuthorised = isAuthorised;
|
IsAuthorised = isAuthorised;
|
||||||
IsCached = isCached;
|
IsCached = isCached;
|
||||||
IsQos = isQos;
|
|
||||||
EnableRateLimiting = isEnableRateLimiting;
|
EnableRateLimiting = isEnableRateLimiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAuthenticated { get; private set; }
|
public bool IsAuthenticated { get; private set; }
|
||||||
public bool IsAuthorised { get; private set; }
|
public bool IsAuthorised { get; private set; }
|
||||||
public bool IsCached { get; private set; }
|
public bool IsCached { get; private set; }
|
||||||
public bool IsQos { get; private set; }
|
|
||||||
public bool EnableRateLimiting { get; private set; }
|
public bool EnableRateLimiting { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,18 @@ namespace Ocelot.Configuration.Repository
|
|||||||
var internalConfig = repo.Get();
|
var internalConfig = repo.Get();
|
||||||
|
|
||||||
_configurationKey = "InternalConfiguration";
|
_configurationKey = "InternalConfiguration";
|
||||||
var consulHost = "localhost";
|
|
||||||
var consulPort = 8500;
|
|
||||||
string token = null;
|
string token = null;
|
||||||
|
|
||||||
if (!internalConfig.IsError)
|
if (!internalConfig.IsError)
|
||||||
{
|
{
|
||||||
consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host;
|
token = internalConfig.Data.ServiceProviderConfiguration.Token;
|
||||||
consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort;
|
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey) ?
|
||||||
token = internalConfig.Data.ServiceProviderConfiguration?.Token;
|
internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey : _configurationKey;
|
||||||
_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);
|
_consul = factory.Get(config);
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,9 @@ namespace Ocelot.DependencyInjection
|
|||||||
_services.TryAddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
_services.TryAddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
||||||
_services.TryAddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
|
_services.TryAddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
|
||||||
_services.TryAddSingleton<IDownstreamPathPlaceholderReplacer, DownstreamTemplatePathPlaceholderReplacer>();
|
_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<IHttpRequester, HttpClientHttpRequester>();
|
||||||
_services.TryAddSingleton<IHttpResponder, HttpContextResponder>();
|
_services.TryAddSingleton<IHttpResponder, HttpContextResponder>();
|
||||||
_services.TryAddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>();
|
_services.TryAddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>();
|
||||||
|
@ -0,0 +1,120 @@
|
|||||||
|
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||||
|
{
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
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;
|
||||||
|
private readonly ConcurrentDictionary<string, OkResponse<DownstreamRoute>> _cache;
|
||||||
|
|
||||||
|
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
|
||||||
|
{
|
||||||
|
_qoSOptionsCreator = qoSOptionsCreator;
|
||||||
|
_cache = new ConcurrentDictionary<string, OkResponse<DownstreamRoute>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if(_cache.TryGetValue(loadBalancerKey, out var downstreamRoute))
|
||||||
|
{
|
||||||
|
return downstreamRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
||||||
|
|
||||||
|
_cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute);
|
||||||
|
|
||||||
|
return downstreamRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if(upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||||
|
{
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return upstreamUrlPath
|
||||||
|
.Substring(upstreamUrlPath.IndexOf('/', 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetServiceName(string upstreamUrlPath)
|
||||||
|
{
|
||||||
|
if(upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||||
|
{
|
||||||
|
return upstreamUrlPath
|
||||||
|
.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||||
{
|
{
|
||||||
public class DownstreamRouteFinder : IDownstreamRouteFinder
|
public class DownstreamRouteFinder : IDownstreamRouteProvider
|
||||||
{
|
{
|
||||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||||
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
|
private readonly IPlaceholderNameAndValueFinder _placeholderNameAndValueFinder;
|
||||||
@ -18,7 +18,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
|
_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>();
|
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
|
public class DownstreamRouteFinderMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly OcelotRequestDelegate _next;
|
private readonly OcelotRequestDelegate _next;
|
||||||
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
private readonly IDownstreamRouteProviderFactory _factory;
|
||||||
private readonly IInternalConfigurationRepository _repo;
|
private readonly IInternalConfigurationRepository _repo;
|
||||||
private readonly IMultiplexer _multiplexer;
|
private readonly IMultiplexer _multiplexer;
|
||||||
|
|
||||||
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
|
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
|
||||||
IOcelotLoggerFactory loggerFactory,
|
IOcelotLoggerFactory loggerFactory,
|
||||||
IDownstreamRouteFinder downstreamRouteFinder,
|
IDownstreamRouteProviderFactory downstreamRouteFinder,
|
||||||
IInternalConfigurationRepository repo,
|
IInternalConfigurationRepository repo,
|
||||||
IMultiplexer multiplexer)
|
IMultiplexer multiplexer)
|
||||||
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
|
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
|
||||||
@ -26,7 +26,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
_repo = repo;
|
_repo = repo;
|
||||||
_multiplexer = multiplexer;
|
_multiplexer = multiplexer;
|
||||||
_next = next;
|
_next = next;
|
||||||
_downstreamRouteFinder = downstreamRouteFinder;
|
_factory = downstreamRouteFinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(DownstreamContext context)
|
public async Task Invoke(DownstreamContext context)
|
||||||
@ -35,20 +35,11 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
|
|
||||||
var upstreamHost = context.HttpContext.Request.Headers["Host"];
|
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}");
|
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)
|
if (downstreamRoute.IsError)
|
||||||
{
|
{
|
||||||
|
@ -73,7 +73,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
private static bool ServiceFabricRequest(DownstreamContext context)
|
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)
|
private static bool RequestForStatefullService(string query)
|
||||||
|
@ -9,6 +9,8 @@ using Ocelot.Middleware;
|
|||||||
|
|
||||||
namespace Ocelot.Errors.Middleware
|
namespace Ocelot.Errors.Middleware
|
||||||
{
|
{
|
||||||
|
using Configuration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Catches all unhandled exceptions thrown by middleware, logs and returns a 500
|
/// Catches all unhandled exceptions thrown by middleware, logs and returns a 500
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,7 +35,19 @@ namespace Ocelot.Errors.Middleware
|
|||||||
{
|
{
|
||||||
try
|
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");
|
Logger.LogDebug("ocelot pipeline started");
|
||||||
|
|
||||||
@ -53,19 +67,9 @@ namespace Ocelot.Errors.Middleware
|
|||||||
Logger.LogDebug("ocelot pipeline finished");
|
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...
|
var key = configuration.RequestId;
|
||||||
//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;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
|
if (!string.IsNullOrEmpty(key) && context.HttpContext.Request.Headers.TryGetValue(key, out var upstreamRequestIds))
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
|
|||||||
var bus = new InMemoryBus<StickySession>();
|
var bus = new InMemoryBus<StickySession>();
|
||||||
return new CookieStickySessions(loadBalancer, reRoute.LoadBalancerOptions.Key, reRoute.LoadBalancerOptions.ExpiryInMs, bus);
|
return new CookieStickySessions(loadBalancer, reRoute.LoadBalancerOptions.Key, reRoute.LoadBalancerOptions.ExpiryInMs, bus);
|
||||||
default:
|
default:
|
||||||
return new NoLoadBalancer(await serviceProvider.Get());
|
return new NoLoadBalancer(async () => await serviceProvider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
@ -9,22 +10,23 @@ namespace Ocelot.LoadBalancer.LoadBalancers
|
|||||||
{
|
{
|
||||||
public class NoLoadBalancer : ILoadBalancer
|
public class NoLoadBalancer : ILoadBalancer
|
||||||
{
|
{
|
||||||
private readonly List<Service> _services;
|
private readonly Func<Task<List<Service>>> _services;
|
||||||
|
|
||||||
public NoLoadBalancer(List<Service> services)
|
public NoLoadBalancer(Func<Task<List<Service>>> services)
|
||||||
{
|
{
|
||||||
_services = services;
|
_services = services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
||||||
{
|
{
|
||||||
//todo no point spinning a task up here, also first or default could be null..
|
var services = await _services();
|
||||||
if (_services == null || _services.Count == 0)
|
//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"));
|
return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var service = await Task.FromResult(_services.FirstOrDefault());
|
var service = await Task.FromResult(services.FirstOrDefault());
|
||||||
return new OkResponse<ServiceHostAndPort>(service.HostAndPort);
|
return new OkResponse<ServiceHostAndPort>(service.HostAndPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,13 +20,13 @@ namespace Ocelot.LoadBalancer.LoadBalancers
|
|||||||
|
|
||||||
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
||||||
{
|
{
|
||||||
var services = await _services.Invoke();
|
var services = await _services();
|
||||||
if (_last >= services.Count)
|
if (_last >= services.Count)
|
||||||
{
|
{
|
||||||
_last = 0;
|
_last = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var next = await Task.FromResult(services[_last]);
|
var next = services[_last];
|
||||||
_last++;
|
_last++;
|
||||||
return new OkResponse<ServiceHostAndPort>(next.HostAndPort);
|
return new OkResponse<ServiceHostAndPort>(next.HostAndPort);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace Ocelot.LoadBalancer.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(DownstreamContext context)
|
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)
|
if(loadBalancer.IsError)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
|
Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Errors;
|
using Ocelot.Errors;
|
||||||
using Ocelot.Middleware.Multiplexer;
|
|
||||||
using Ocelot.Request.Middleware;
|
using Ocelot.Request.Middleware;
|
||||||
|
|
||||||
namespace Ocelot.Middleware
|
namespace Ocelot.Middleware
|
||||||
@ -20,8 +17,6 @@ namespace Ocelot.Middleware
|
|||||||
|
|
||||||
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
|
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; set; }
|
||||||
|
|
||||||
public ServiceProviderConfiguration ServiceProviderConfiguration {get; set;}
|
|
||||||
|
|
||||||
public HttpContext HttpContext { get; }
|
public HttpContext HttpContext { get; }
|
||||||
|
|
||||||
public DownstreamReRoute DownstreamReRoute { get; set; }
|
public DownstreamReRoute DownstreamReRoute { get; set; }
|
||||||
@ -32,6 +27,8 @@ namespace Ocelot.Middleware
|
|||||||
|
|
||||||
public List<Error> Errors { get; }
|
public List<Error> Errors { get; }
|
||||||
|
|
||||||
|
public IInternalConfiguration Configuration { get; set; }
|
||||||
|
|
||||||
public bool IsError => Errors.Count > 0;
|
public bool IsError => Errors.Count > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace Ocelot.Middleware.Multiplexer
|
|||||||
var downstreamContext = new DownstreamContext(context.HttpContext)
|
var downstreamContext = new DownstreamContext(context.HttpContext)
|
||||||
{
|
{
|
||||||
TemplatePlaceholderNameAndValues = context.TemplatePlaceholderNameAndValues,
|
TemplatePlaceholderNameAndValues = context.TemplatePlaceholderNameAndValues,
|
||||||
ServiceProviderConfiguration = context.ServiceProviderConfiguration,
|
Configuration = context.Configuration,
|
||||||
DownstreamReRoute = reRoute.DownstreamReRoute[i],
|
DownstreamReRoute = reRoute.DownstreamReRoute[i],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ namespace Ocelot.Requester
|
|||||||
handlers.Add(() => (DelegatingHandler)_factory.Get());
|
handlers.Add(() => (DelegatingHandler)_factory.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.IsQos)
|
if (request.QosOptions.UseQos)
|
||||||
{
|
{
|
||||||
var qosProvider = _qosProviderHouse.Get(request);
|
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}");
|
.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
|
? _defaultTimeout
|
||||||
: TimeSpan.FromMilliseconds(context.DownstreamReRoute.QosOptionsOptions.TimeoutValue);
|
: TimeSpan.FromMilliseconds(context.DownstreamReRoute.QosOptions.TimeoutValue);
|
||||||
|
|
||||||
_httpClient = new HttpClient(CreateHttpMessageHandler(httpclientHandler, context.DownstreamReRoute))
|
_httpClient = new HttpClient(CreateHttpMessageHandler(httpclientHandler, context.DownstreamReRoute))
|
||||||
{
|
{
|
||||||
|
@ -19,15 +19,15 @@ namespace Ocelot.Requester.QoS
|
|||||||
{
|
{
|
||||||
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();
|
_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
|
_circuitBreakerPolicy = Policy
|
||||||
.Handle<HttpRequestException>()
|
.Handle<HttpRequestException>()
|
||||||
.Or<TimeoutRejectedException>()
|
.Or<TimeoutRejectedException>()
|
||||||
.Or<TimeoutException>()
|
.Or<TimeoutException>()
|
||||||
.CircuitBreakerAsync(
|
.CircuitBreakerAsync(
|
||||||
exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking,
|
exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking,
|
||||||
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak),
|
durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptions.DurationOfBreak),
|
||||||
onBreak: (ex, breakDelay) =>
|
onBreak: (ex, breakDelay) =>
|
||||||
{
|
{
|
||||||
_logger.LogError(
|
_logger.LogError(
|
||||||
|
@ -14,7 +14,7 @@ namespace Ocelot.Requester.QoS
|
|||||||
|
|
||||||
public IQoSProvider Get(DownstreamReRoute reRoute)
|
public IQoSProvider Get(DownstreamReRoute reRoute)
|
||||||
{
|
{
|
||||||
if (reRoute.IsQos)
|
if (reRoute.QosOptions.UseQos)
|
||||||
{
|
{
|
||||||
return new PollyQoSProvider(reRoute, _loggerFactory);
|
return new PollyQoSProvider(reRoute, _loggerFactory);
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,26 @@ namespace Ocelot.Requester.QoS
|
|||||||
{
|
{
|
||||||
try
|
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);
|
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);
|
qosProvider = _qoSProviderFactory.Get(reRoute);
|
||||||
Add(reRoute.QosKey, qosProvider);
|
Add(reRoute.QosOptions.Key, qosProvider);
|
||||||
return new OkResponse<IQoSProvider>(qosProvider);
|
return new OkResponse<IQoSProvider>(qosProvider);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return new ErrorResponse<IQoSProvider>(new List<Ocelot.Errors.Error>()
|
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)
|
public ConsulRegistryConfiguration(string host, int port, string keyOfServiceInConsul, string token)
|
||||||
{
|
{
|
||||||
Host = host;
|
Host = string.IsNullOrEmpty(host) ? "localhost" : host;
|
||||||
Port = port;
|
Port = port > 0 ? port : 8500;
|
||||||
KeyOfServiceInConsul = keyOfServiceInConsul;
|
KeyOfServiceInConsul = keyOfServiceInConsul;
|
||||||
Token = token;
|
Token = token;
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,7 @@ namespace Ocelot.ServiceDiscovery.Providers
|
|||||||
{;
|
{;
|
||||||
_logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
|
_logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
|
||||||
|
|
||||||
var consulHost = string.IsNullOrEmpty(config?.Host) ? "localhost" : config.Host;
|
_config = config;
|
||||||
|
|
||||||
var consulPort = config?.Port ?? 8500;
|
|
||||||
|
|
||||||
_config = new ConsulRegistryConfiguration(consulHost, consulPort, config?.KeyOfServiceInConsul, config?.Token);
|
|
||||||
|
|
||||||
_consul = clientFactory.Get(_config);
|
_consul = clientFactory.Get(_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +208,121 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.BDDfy();
|
.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]
|
[Fact]
|
||||||
public void should_use_token_to_make_request_to_consul()
|
public void should_use_token_to_make_request_to_consul()
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
|
|
||||||
_internalRepo
|
_internalRepo
|
||||||
.Setup(x => x.Get())
|
.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);
|
_repo = new ConsulFileConfigurationRepository(_cache.Object, _internalRepo.Object, _factory.Object, _loggerFactory.Object);
|
||||||
}
|
}
|
||||||
@ -140,7 +140,10 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
_internalRepo
|
_internalRepo
|
||||||
.Setup(x => x.Get())
|
.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);
|
_repo = new ConsulFileConfigurationRepository(_cache.Object, _internalRepo.Object, _factory.Object, _loggerFactory.Object);
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
var fileConfig = new FileConfiguration();
|
var fileConfig = new FileConfiguration();
|
||||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
|
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))
|
this.Given(x => GivenTheFollowingConfiguration(fileConfig))
|
||||||
.And(x => GivenTheRepoReturns(new OkResponse()))
|
.And(x => GivenTheRepoReturns(new OkResponse()))
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithReRouteKey("CookieStickySessions:sessionid")
|
.WithLoadBalancerKey("CookieStickySessions:sessionid")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -199,7 +199,7 @@
|
|||||||
.WithDownstreamScheme("http")
|
.WithDownstreamScheme("http")
|
||||||
.WithUpstreamHttpMethod(new List<string>() {"Get"})
|
.WithUpstreamHttpMethod(new List<string>() {"Get"})
|
||||||
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() {new DownstreamHostAndPort("localhost", 51878)})
|
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() {new DownstreamHostAndPort("localhost", 51878)})
|
||||||
.WithReRouteKey("/laura|Get")
|
.WithLoadBalancerKey("/laura|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var lauraReRoute = new ReRouteBuilder()
|
var lauraReRoute = new ReRouteBuilder()
|
||||||
@ -218,7 +218,7 @@
|
|||||||
.WithDownstreamScheme("http")
|
.WithDownstreamScheme("http")
|
||||||
.WithUpstreamHttpMethod(new List<string>() { "Get" })
|
.WithUpstreamHttpMethod(new List<string>() { "Get" })
|
||||||
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() { new DownstreamHostAndPort("localhost", 51878) })
|
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() { new DownstreamHostAndPort("localhost", 51878) })
|
||||||
.WithReRouteKey("/tom|Get")
|
.WithLoadBalancerKey("/tom|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var tomReRoute = new ReRouteBuilder()
|
var tomReRoute = new ReRouteBuilder()
|
||||||
@ -361,7 +361,6 @@
|
|||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var serviceOptions = new ReRouteOptionsBuilder()
|
var serviceOptions = new ReRouteOptionsBuilder()
|
||||||
.WithIsQos(true)
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -410,7 +409,7 @@
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -462,7 +461,7 @@
|
|||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithDelegatingHandlers(handlers)
|
.WithDelegatingHandlers(handlers)
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -507,7 +506,7 @@
|
|||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithUseServiceDiscovery(true)
|
.WithUseServiceDiscovery(true)
|
||||||
.WithServiceName("ProductService")
|
.WithServiceName("ProductService")
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -558,7 +557,7 @@
|
|||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithUseServiceDiscovery(false)
|
.WithUseServiceDiscovery(false)
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -601,7 +600,7 @@
|
|||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -646,7 +645,7 @@
|
|||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithRequestIdKey("blahhhh")
|
.WithRequestIdKey("blahhhh")
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
@ -741,7 +740,7 @@
|
|||||||
{
|
{
|
||||||
new ClaimToThing("CustomerId", "CustomerId", "", 0),
|
new ClaimToThing("CustomerId", "CustomerId", "", 0),
|
||||||
})
|
})
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var expected = new List<ReRoute>
|
var expected = new List<ReRoute>
|
||||||
@ -784,7 +783,7 @@
|
|||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithAuthenticationOptions(authenticationOptions)
|
.WithAuthenticationOptions(authenticationOptions)
|
||||||
.WithReRouteKey("/api/products/{productId}|Get")
|
.WithLoadBalancerKey("/api/products/{productId}|Get")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var expected = new List<ReRoute>
|
var expected = new List<ReRoute>
|
||||||
@ -942,16 +941,15 @@
|
|||||||
private void GivenTheQosOptionsCreatorReturns(QoSOptions qosOptions)
|
private void GivenTheQosOptionsCreatorReturns(QoSOptions qosOptions)
|
||||||
{
|
{
|
||||||
_qosOptionsCreator
|
_qosOptionsCreator
|
||||||
.Setup(x => x.Create(_fileConfiguration.ReRoutes[0]))
|
.Setup(x => x.Create(_fileConfiguration.ReRoutes[0].QoSOptions, It.IsAny<string>(), It.IsAny<string[]>()))
|
||||||
.Returns(qosOptions);
|
.Returns(qosOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheQosOptionsAre(QoSOptions qosOptions)
|
private void ThenTheQosOptionsAre(QoSOptions qosOptions)
|
||||||
{
|
{
|
||||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
|
_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].QosOptionsOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
|
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
|
||||||
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheServiceProviderCreatorIsCalledCorrectly()
|
private void ThenTheServiceProviderCreatorIsCalledCorrectly()
|
||||||
@ -992,13 +990,13 @@
|
|||||||
|
|
||||||
private void GivenTheFollowingHttpHandlerOptionsAreReturned(HttpHandlerOptions httpHandlerOptions)
|
private void GivenTheFollowingHttpHandlerOptionsAreReturned(HttpHandlerOptions httpHandlerOptions)
|
||||||
{
|
{
|
||||||
_httpHandlerOptionsCreator.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
_httpHandlerOptionsCreator.Setup(x => x.Create(It.IsAny<FileHttpHandlerOptions>()))
|
||||||
.Returns(httpHandlerOptions);
|
.Returns(httpHandlerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheHttpHandlerOptionsCreatorIsCalledCorrectly()
|
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()
|
private void GivenTheDownstreamAddresses()
|
||||||
|
@ -103,7 +103,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
|
|
||||||
private void WhenICreateHttpHandlerOptions()
|
private void WhenICreateHttpHandlerOptions()
|
||||||
{
|
{
|
||||||
_httpHandlerOptions = _httpHandlerOptionsCreator.Create(_fileReRoute);
|
_httpHandlerOptions = _httpHandlerOptionsCreator.Create(_fileReRoute.HttpHandlerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingOptionsReturned(HttpHandlerOptions expected)
|
private void ThenTheFollowingOptionsReturned(HttpHandlerOptions expected)
|
||||||
|
@ -105,6 +105,10 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
|
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
|
||||||
|
|
||||||
public string RequestId {get;}
|
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()
|
private void WhenICreate()
|
||||||
{
|
{
|
||||||
_result = _creator.Create(_fileReRoute);
|
_result = _creator.Create(_fileReRoute.QoSOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingIsReturned(QoSOptions expected)
|
private void ThenTheFollowingIsReturned(QoSOptions expected)
|
||||||
|
@ -29,11 +29,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
EnableRateLimiting = true
|
EnableRateLimiting = true
|
||||||
},
|
},
|
||||||
QoSOptions = new FileQoSOptions
|
|
||||||
{
|
|
||||||
ExceptionsAllowedBeforeBreaking = 1,
|
|
||||||
TimeoutValue = 1
|
|
||||||
},
|
|
||||||
AuthenticationOptions = new FileAuthenticationOptions()
|
AuthenticationOptions = new FileAuthenticationOptions()
|
||||||
{
|
{
|
||||||
AuthenticationProviderKey = "Test"
|
AuthenticationProviderKey = "Test"
|
||||||
@ -52,7 +47,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.WithIsAuthenticated(true)
|
.WithIsAuthenticated(true)
|
||||||
.WithIsAuthorised(true)
|
.WithIsAuthorised(true)
|
||||||
.WithIsCached(true)
|
.WithIsCached(true)
|
||||||
.WithIsQos(true)
|
|
||||||
.WithRateLimiting(true)
|
.WithRateLimiting(true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -76,7 +70,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
_result.IsAuthenticated.ShouldBe(expected.IsAuthenticated);
|
_result.IsAuthenticated.ShouldBe(expected.IsAuthenticated);
|
||||||
_result.IsAuthorised.ShouldBe(expected.IsAuthorised);
|
_result.IsAuthorised.ShouldBe(expected.IsAuthorised);
|
||||||
_result.IsQos.ShouldBe(expected.IsQos);
|
|
||||||
_result.IsCached.ShouldBe(expected.IsCached);
|
_result.IsCached.ShouldBe(expected.IsCached);
|
||||||
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
|
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,268 @@
|
|||||||
|
using Ocelot.DownstreamRouteFinder.Finder;
|
||||||
|
using Xunit;
|
||||||
|
using Shouldly;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
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;
|
||||||
|
private Response<DownstreamRoute> _resultTwo;
|
||||||
|
|
||||||
|
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_cache_downstream_route()
|
||||||
|
{
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, "/geoffisthebest/"))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.And(_ => GivenTheConfiguration(configuration, "/geoffisthebest/"))
|
||||||
|
.When(_ => WhenICreateAgain())
|
||||||
|
.Then(_ => ThenTheDownstreamRoutesAreTheSameReference())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_cache_downstream_route()
|
||||||
|
{
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, "/geoffistheworst/"))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.And(_ => GivenTheConfiguration(configuration, "/geoffisthebest/"))
|
||||||
|
.When(_ => WhenICreateAgain())
|
||||||
|
.Then(_ => ThenTheDownstreamRoutesAreTheNotSameReference())
|
||||||
|
.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_with_only_first_segment_no_traling_slash()
|
||||||
|
{
|
||||||
|
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_with_segments_no_traling_slash()
|
||||||
|
{
|
||||||
|
var upstreamUrlPath = "/auth/test";
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, upstreamUrlPath))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.Then(_ => ThenThePathDoesNotHaveTrailingSlash())
|
||||||
|
.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 ThenThePathDoesNotHaveTrailingSlash()
|
||||||
|
{
|
||||||
|
_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 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenICreateAgain()
|
||||||
|
{
|
||||||
|
_resultTwo = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheDownstreamRoutesAreTheSameReference()
|
||||||
|
{
|
||||||
|
_result.ShouldBe(_resultTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheDownstreamRoutesAreTheNotSameReference()
|
||||||
|
{
|
||||||
|
_result.ShouldNotBe(_resultTwo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
public class DownstreamRouteFinderMiddlewareTests
|
public class DownstreamRouteFinderMiddlewareTests
|
||||||
{
|
{
|
||||||
private readonly Mock<IDownstreamRouteFinder> _finder;
|
private readonly Mock<IDownstreamRouteProvider> _finder;
|
||||||
|
private readonly Mock<IDownstreamRouteProviderFactory> _factory;
|
||||||
private readonly Mock<IInternalConfigurationRepository> _repo;
|
private readonly Mock<IInternalConfigurationRepository> _repo;
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private IInternalConfiguration _config;
|
private IInternalConfiguration _config;
|
||||||
@ -35,20 +36,22 @@
|
|||||||
public DownstreamRouteFinderMiddlewareTests()
|
public DownstreamRouteFinderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_repo = new Mock<IInternalConfigurationRepository>();
|
_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());
|
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
|
||||||
_next = context => Task.CompletedTask;
|
_next = context => Task.CompletedTask;
|
||||||
_multiplexer = new Mock<IMultiplexer>();
|
_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]
|
[Fact]
|
||||||
public void should_call_scoped_data_repository_correctly()
|
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()
|
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("any old string")
|
.WithDownstreamPathTemplate("any old string")
|
||||||
@ -76,23 +79,21 @@
|
|||||||
private void GivenTheFollowingConfig(IInternalConfiguration config)
|
private void GivenTheFollowingConfig(IInternalConfiguration config)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_repo
|
_downstreamContext.Configuration = config;
|
||||||
.Setup(x => x.Get())
|
|
||||||
.Returns(new OkResponse<IInternalConfiguration>(_config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_finder
|
_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);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
|
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_downstreamContext.TemplatePlaceholderNameAndValues.ShouldBe(_downstreamRoute.Data.TemplatePlaceholderNameAndValues);
|
_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
|
public class DownstreamRouteFinderTests
|
||||||
{
|
{
|
||||||
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
private readonly IDownstreamRouteProvider _downstreamRouteFinder;
|
||||||
private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher;
|
private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher;
|
||||||
private readonly Mock<IPlaceholderNameAndValueFinder> _finder;
|
private readonly Mock<IPlaceholderNameAndValueFinder> _finder;
|
||||||
private string _upstreamUrlPath;
|
private string _upstreamUrlPath;
|
||||||
@ -709,7 +709,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
|
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
|
||||||
{
|
{
|
||||||
_reRoutesConfig = reRoutesConfig;
|
_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)
|
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
|
||||||
@ -719,7 +719,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
|
|
||||||
private void WhenICallTheFinder()
|
private void WhenICallTheFinder()
|
||||||
{
|
{
|
||||||
_result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod, _config, _upstreamHost);
|
_result = _downstreamRouteFinder.Get(_upstreamUrlPath, _upstreamHttpMethod, _config, _upstreamHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingIsReturned(DownstreamRoute expected)
|
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)
|
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()
|
private void WhenICallTheMiddleware()
|
||||||
|
@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.Errors
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void NoDownstreamException()
|
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())
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
.And(_ => GivenTheConfigurationIs(config))
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
@ -64,7 +64,7 @@ namespace Ocelot.UnitTests.Errors
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void DownstreamException()
|
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())
|
this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
|
||||||
.And(_ => GivenTheConfigurationIs(config))
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Errors
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldSetRequestId()
|
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())
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
.And(_ => GivenTheConfigurationIs(config))
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.Errors
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldSetAspDotNetRequestId()
|
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())
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
.And(_ => GivenTheConfigurationIs(config))
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
|
@ -33,7 +33,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
public void should_store_load_balancer_on_first_request()
|
public void should_store_load_balancer_on_first_request()
|
||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithReRouteKey("test")
|
.WithLoadBalancerKey("test")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||||
@ -46,7 +46,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
||||||
.WithReRouteKey("test")
|
.WithLoadBalancerKey("test")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||||
@ -60,12 +60,12 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
||||||
.WithReRouteKey("test")
|
.WithLoadBalancerKey("test")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var reRouteTwo = new DownstreamReRouteBuilder()
|
var reRouteTwo = new DownstreamReRouteBuilder()
|
||||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeRoundRobinLoadBalancer", "", 0))
|
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeRoundRobinLoadBalancer", "", 0))
|
||||||
.WithReRouteKey("testtwo")
|
.WithLoadBalancerKey("testtwo")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||||
@ -92,12 +92,12 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancer", "", 0))
|
||||||
.WithReRouteKey("test")
|
.WithLoadBalancerKey("test")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var reRouteTwo = new DownstreamReRouteBuilder()
|
var reRouteTwo = new DownstreamReRouteBuilder()
|
||||||
.WithLoadBalancerOptions(new LoadBalancerOptions("LeastConnection", "", 0))
|
.WithLoadBalancerOptions(new LoadBalancerOptions("LeastConnection", "", 0))
|
||||||
.WithReRouteKey("test")
|
.WithLoadBalancerKey("test")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
|
||||||
|
@ -117,7 +117,8 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
|
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
|
||||||
{
|
{
|
||||||
_config = 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)
|
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.LoadBalancer.LoadBalancers;
|
||||||
|
using Shouldly;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.LoadBalancer
|
||||||
|
{
|
||||||
|
public class LoadBalancerOptionsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void should_default_to_no_load_balancer()
|
||||||
|
{
|
||||||
|
var options = new LoadBalancerOptionsBuilder().Build();
|
||||||
|
options.Type.ShouldBe(nameof(NoLoadBalancer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.LoadBalancer.LoadBalancers;
|
using Ocelot.LoadBalancer.LoadBalancers;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
@ -16,6 +18,12 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
private NoLoadBalancer _loadBalancer;
|
private NoLoadBalancer _loadBalancer;
|
||||||
private Response<ServiceHostAndPort> _result;
|
private Response<ServiceHostAndPort> _result;
|
||||||
|
|
||||||
|
public NoLoadBalancerTests()
|
||||||
|
{
|
||||||
|
_services = new List<Service>();
|
||||||
|
_loadBalancer = new NoLoadBalancer(() => Task.FromResult(_services));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_host_and_port()
|
public void should_return_host_and_port()
|
||||||
{
|
{
|
||||||
@ -25,6 +33,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
{
|
{
|
||||||
new Service("product", hostAndPort, string.Empty, string.Empty, new string[0])
|
new Service("product", hostAndPort, string.Empty, string.Empty, new string[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenServices(services))
|
this.Given(x => x.GivenServices(services))
|
||||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||||
.Then(x => x.ThenTheHostAndPortIs(hostAndPort))
|
.Then(x => x.ThenTheHostAndPortIs(hostAndPort))
|
||||||
@ -34,25 +43,43 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_error_if_no_services()
|
public void should_return_error_if_no_services()
|
||||||
{
|
{
|
||||||
var services = new List<Service>();
|
this.When(x => x.WhenIGetTheNextHostAndPort())
|
||||||
|
|
||||||
this.Given(x => x.GivenServices(services))
|
|
||||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
|
||||||
.Then(x => x.ThenThereIsAnError())
|
.Then(x => x.ThenThereIsAnError())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_error_if_no_services_then_when_services_available_return_host_and_port()
|
||||||
|
{
|
||||||
|
var hostAndPort = new ServiceHostAndPort("127.0.0.1", 80);
|
||||||
|
|
||||||
|
var services = new List<Service>
|
||||||
|
{
|
||||||
|
new Service("product", hostAndPort, string.Empty, string.Empty, new string[0])
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(_ => WhenIGetTheNextHostAndPort())
|
||||||
|
.And(_ => ThenThereIsAnError())
|
||||||
|
.And(_ => GivenServices(services))
|
||||||
|
.When(_ => WhenIGetTheNextHostAndPort())
|
||||||
|
.Then(_ => ThenTheHostAndPortIs(hostAndPort))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_error_if_null_services()
|
public void should_return_error_if_null_services()
|
||||||
{
|
{
|
||||||
List<Service> services = null;
|
this.Given(x => x.GivenServicesAreNull())
|
||||||
|
|
||||||
this.Given(x => x.GivenServices(services))
|
|
||||||
.When(x => x.WhenIGetTheNextHostAndPort())
|
.When(x => x.WhenIGetTheNextHostAndPort())
|
||||||
.Then(x => x.ThenThereIsAnError())
|
.Then(x => x.ThenThereIsAnError())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenServicesAreNull()
|
||||||
|
{
|
||||||
|
_loadBalancer = new NoLoadBalancer(() => Task.FromResult((List<Service>)null));
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenThereIsAnError()
|
private void ThenThereIsAnError()
|
||||||
{
|
{
|
||||||
_result.IsError.ShouldBeTrue();
|
_result.IsError.ShouldBeTrue();
|
||||||
@ -60,12 +87,11 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
|
|
||||||
private void GivenServices(List<Service> services)
|
private void GivenServices(List<Service> services)
|
||||||
{
|
{
|
||||||
_services = services;
|
_services.AddRange(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenIGetTheNextHostAndPort()
|
private void WhenIGetTheNextHostAndPort()
|
||||||
{
|
{
|
||||||
_loadBalancer = new NoLoadBalancer(_services);
|
|
||||||
_result = _loadBalancer.Lease(new DownstreamContext(new DefaultHttpContext())).Result;
|
_result = _loadBalancer.Lease(new DownstreamContext(new DefaultHttpContext())).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,14 +38,21 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_follow_ordering_add_specifics()
|
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))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
.WithDelegatingHandlers(new List<string>
|
.WithDelegatingHandlers(new List<string>
|
||||||
{
|
{
|
||||||
"FakeDelegatingHandler",
|
"FakeDelegatingHandler",
|
||||||
"FakeDelegatingHandlerTwo"
|
"FakeDelegatingHandlerTwo"
|
||||||
})
|
})
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
@ -67,7 +74,14 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_follow_ordering_order_specifics_and_globals()
|
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))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
.WithDelegatingHandlers(new List<string>
|
.WithDelegatingHandlers(new List<string>
|
||||||
{
|
{
|
||||||
@ -75,7 +89,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
"FakeDelegatingHandler",
|
"FakeDelegatingHandler",
|
||||||
"FakeDelegatingHandlerFour"
|
"FakeDelegatingHandlerFour"
|
||||||
})
|
})
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
@ -97,14 +111,21 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_follow_ordering_order_specifics()
|
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))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
.WithDelegatingHandlers(new List<string>
|
.WithDelegatingHandlers(new List<string>
|
||||||
{
|
{
|
||||||
"FakeDelegatingHandlerTwo",
|
"FakeDelegatingHandlerTwo",
|
||||||
"FakeDelegatingHandler"
|
"FakeDelegatingHandler"
|
||||||
})
|
})
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
@ -126,13 +147,20 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_follow_ordering_order_and_only_add_specifics_in_config()
|
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))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
.WithDelegatingHandlers(new List<string>
|
.WithDelegatingHandlers(new List<string>
|
||||||
{
|
{
|
||||||
"FakeDelegatingHandler",
|
"FakeDelegatingHandler",
|
||||||
})
|
})
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
@ -153,9 +181,16 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_follow_ordering_dont_add_specifics()
|
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))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
@ -175,14 +210,18 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_apply_re_route_specific()
|
public void should_apply_re_route_specific()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false))
|
||||||
.WithDelegatingHandlers(new List<string>
|
.WithDelegatingHandlers(new List<string>
|
||||||
{
|
{
|
||||||
"FakeDelegatingHandler",
|
"FakeDelegatingHandler",
|
||||||
"FakeDelegatingHandlerTwo"
|
"FakeDelegatingHandlerTwo"
|
||||||
})
|
})
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
@ -197,8 +236,15 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_all_from_all_routes_provider_and_qos()
|
public void should_all_from_all_routes_provider_and_qos()
|
||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
.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))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
@ -213,8 +259,12 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_provider_with_no_delegates()
|
public void should_return_provider_with_no_delegates()
|
||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(false)
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
.Build();
|
||||||
|
|
||||||
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithQosOptions(qosOptions)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithLoadBalancerKey("").Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheServiceProviderReturnsNothing())
|
.And(x => GivenTheServiceProviderReturnsNothing())
|
||||||
@ -226,8 +276,15 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_provider_with_qos_delegate()
|
public void should_return_provider_with_qos_delegate()
|
||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
.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))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
@ -241,8 +298,15 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_error()
|
public void should_return_error()
|
||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
.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))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
|
.And(x => GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
|
||||||
|
@ -46,10 +46,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_build_http_client()
|
public void should_build_http_client()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -63,10 +66,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_log_if_ignoring_ssl_errors()
|
public void should_log_if_ignoring_ssl_errors()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.WithDangerousAcceptAnyServerCertificateValidator(true)
|
.WithDangerousAcceptAnyServerCertificateValidator(true)
|
||||||
.Build();
|
.Build();
|
||||||
@ -82,10 +88,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_delegating_handlers_in_order()
|
public void should_call_delegating_handlers_in_order()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -110,10 +119,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_re_use_cookies_from_container()
|
public void should_re_use_cookies_from_container()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -142,10 +154,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
HttpMethod method = new HttpMethod(verb);
|
HttpMethod method = new HttpMethod(verb);
|
||||||
|
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -47,10 +47,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_request_correctly()
|
public void should_call_request_correctly()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -70,10 +73,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_request_unable_to_complete_request()
|
public void should_call_request_unable_to_complete_request()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -92,10 +98,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void http_client_request_times_out()
|
public void http_client_request_times_out()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithIsQos(false)
|
.WithQosOptions(qosOptions)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false))
|
||||||
.WithReRouteKey("")
|
.WithLoadBalancerKey("")
|
||||||
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())
|
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -31,9 +31,12 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_no_qos_provider()
|
public void should_return_no_qos_provider()
|
||||||
{
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithQosOptions(qosOptions)
|
||||||
.WithUpstreamHttpMethod(new List<string> { "get" })
|
.WithUpstreamHttpMethod(new List<string> { "get" })
|
||||||
.WithIsQos(false)
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenAReRoute(reRoute))
|
this.Given(x => x.GivenAReRoute(reRoute))
|
||||||
@ -53,7 +56,6 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder()
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
.WithUpstreamHttpMethod(new List<string> { "get" })
|
.WithUpstreamHttpMethod(new List<string> { "get" })
|
||||||
.WithIsQos(true)
|
|
||||||
.WithQosOptions(qosOptions)
|
.WithQosOptions(qosOptions)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -26,7 +26,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_store_qos_provider_on_first_request()
|
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()))
|
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||||
.Then(x => x.ThenItIsAdded())
|
.Then(x => x.ThenItIsAdded())
|
||||||
@ -36,7 +42,13 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_not_store_qos_provider_on_first_request()
|
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()))
|
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||||
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
||||||
@ -47,8 +59,21 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_store_qos_providers_by_key()
|
public void should_store_qos_providers_by_key()
|
||||||
{
|
{
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithQosKey("test").Build();
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
var reRouteTwo = new DownstreamReRouteBuilder().WithQosKey("testTwo").Build();
|
.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()))
|
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||||
.And(x => x.GivenThereIsAQoSProvider(reRouteTwo, new FakePollyQoSProvider()))
|
.And(x => x.GivenThereIsAQoSProvider(reRouteTwo, new FakePollyQoSProvider()))
|
||||||
@ -62,7 +87,12 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_error_if_no_qos_provider_with_key()
|
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))
|
this.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
||||||
.Then(x => x.ThenAnErrorIsReturned())
|
.Then(x => x.ThenAnErrorIsReturned())
|
||||||
@ -72,9 +102,24 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_get_new_qos_provider_if_reroute_qos_provider_has_changed()
|
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()))
|
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
|
||||||
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user