mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-01 05:15:27 +08:00 
			
		
		
		
	| @@ -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)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 geffzhang
					geffzhang