Refactor CircuitBreaker Pattern

Add Qos Config in ReRoute And Refactor CircuitBreakingDelegatingHandler
This commit is contained in:
geffzhang 2017-02-03 14:49:46 +08:00
parent e80364a1f8
commit 883be802b3
28 changed files with 600 additions and 259 deletions

View File

@ -32,6 +32,9 @@ namespace Ocelot.Configuration.Builder
private string _downstreamScheme; private string _downstreamScheme;
private string _downstreamHost; private string _downstreamHost;
private int _dsPort; private int _dsPort;
private int _exceptionsAllowedBeforeBreaking;
private int _durationOfBreak;
private int _timeoutValue;
public ReRouteBuilder() public ReRouteBuilder()
{ {
@ -192,6 +195,24 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ReRouteBuilder WithExceptionsAllowedBeforeBreaking(int exceptionsAllowedBeforeBreaking)
{
_exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
return this;
}
public ReRouteBuilder WithDurationOfBreak(int durationOfBreak)
{
_durationOfBreak = durationOfBreak;
return this;
}
public ReRouteBuilder WithTimeoutValue(int timeoutValue)
{
_timeoutValue = timeoutValue;
return this;
}
public ReRoute Build() public ReRoute Build()
{ {
Func<HostAndPort> downstreamHostFunc = () => new HostAndPort(_downstreamHost, _dsPort); Func<HostAndPort> downstreamHostFunc = () => new HostAndPort(_downstreamHost, _dsPort);
@ -200,7 +221,8 @@ namespace Ocelot.Configuration.Builder
_isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName,
_requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement, _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement,
_isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName, _isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName,
_useServiceDiscovery, _serviceDiscoveryAddress, _serviceDiscoveryProvider, downstreamHostFunc, _downstreamScheme); _useServiceDiscovery, _serviceDiscoveryAddress, _serviceDiscoveryProvider, downstreamHostFunc, _downstreamScheme,
_exceptionsAllowedBeforeBreaking,_durationOfBreak, _timeoutValue);
} }
} }
} }

View File

@ -96,7 +96,6 @@ namespace Ocelot.Configuration.Creator
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address) && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address)
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider); && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
Func<HostAndPort> downstreamHostAndPortFunc = () => new HostAndPort(reRoute.DownstreamHost.Trim('/'), reRoute.DownstreamPort); Func<HostAndPort> downstreamHostAndPortFunc = () => new HostAndPort(reRoute.DownstreamHost.Trim('/'), reRoute.DownstreamPort);
if (isAuthenticated) if (isAuthenticated)
@ -116,7 +115,8 @@ namespace Ocelot.Configuration.Creator
reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries, reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries,
requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds), requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds),
reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme); globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme,
reRoute.ExceptionsAllowedBeforeBreaking, reRoute.DurationOfBreak, reRoute.TimeoutValue);
} }
return new ReRoute(new DownstreamPathTemplate(reRoute.DownstreamPathTemplate), reRoute.UpstreamTemplate, return new ReRoute(new DownstreamPathTemplate(reRoute.DownstreamPathTemplate), reRoute.UpstreamTemplate,
@ -125,7 +125,8 @@ namespace Ocelot.Configuration.Creator
reRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>(), reRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>(),
requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds), requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds),
reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme); globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme,
reRoute.ExceptionsAllowedBeforeBreaking, reRoute.DurationOfBreak, reRoute.TimeoutValue);
} }
private string BuildUpstreamTemplate(FileReRoute reRoute) private string BuildUpstreamTemplate(FileReRoute reRoute)

View File

@ -29,5 +29,8 @@ namespace Ocelot.Configuration.File
public string DownstreamScheme {get;set;} public string DownstreamScheme {get;set;}
public string DownstreamHost {get;set;} public string DownstreamHost {get;set;}
public int DownstreamPort { get; set; } public int DownstreamPort { get; set; }
public int ExceptionsAllowedBeforeBreaking { get; set; }
public int DurationOfBreak { get; set; }
public int TimeoutValue { get; set; }
} }
} }

View File

@ -10,7 +10,8 @@ namespace Ocelot.Configuration
bool isAuthenticated, AuthenticationOptions authenticationOptions, List<ClaimToThing> configurationHeaderExtractorProperties, bool isAuthenticated, AuthenticationOptions authenticationOptions, List<ClaimToThing> configurationHeaderExtractorProperties,
List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries, List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries,
string requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery, string requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery,
string serviceDiscoveryProvider, string serviceDiscoveryAddress, Func<HostAndPort> downstreamHostAndPort, string downstreamScheme) string serviceDiscoveryProvider, string serviceDiscoveryAddress, Func<HostAndPort> downstreamHostAndPort, string downstreamScheme,
int exceptionsAllowedBeforeBreaking =3, int durationofBreak =8, int timeoutValue = 5000)
{ {
DownstreamPathTemplate = downstreamPathTemplate; DownstreamPathTemplate = downstreamPathTemplate;
UpstreamTemplate = upstreamTemplate; UpstreamTemplate = upstreamTemplate;
@ -35,6 +36,9 @@ namespace Ocelot.Configuration
ServiceDiscoveryAddress = serviceDiscoveryAddress; ServiceDiscoveryAddress = serviceDiscoveryAddress;
DownstreamHostAndPort = downstreamHostAndPort; DownstreamHostAndPort = downstreamHostAndPort;
DownstreamScheme = downstreamScheme; DownstreamScheme = downstreamScheme;
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
DurationOfBreak = durationofBreak;
TimeoutValue = timeoutValue;
} }
public DownstreamPathTemplate DownstreamPathTemplate { get; private set; } public DownstreamPathTemplate DownstreamPathTemplate { get; private set; }
@ -57,5 +61,8 @@ namespace Ocelot.Configuration
public string ServiceDiscoveryAddress { get; private set;} public string ServiceDiscoveryAddress { get; private set;}
public Func<HostAndPort> DownstreamHostAndPort {get;private set;} public Func<HostAndPort> DownstreamHostAndPort {get;private set;}
public string DownstreamScheme {get;private set;} public string DownstreamScheme {get;private set;}
public int ExceptionsAllowedBeforeBreaking { get; private set; }
public int DurationOfBreak { get; private set; }
public int TimeoutValue { get; private set; }
} }
} }

View File

@ -15,7 +15,8 @@ namespace Ocelot.Request.Builder
IRequestCookieCollection cookies, IRequestCookieCollection cookies,
QueryString queryString, QueryString queryString,
string contentType, string contentType,
RequestId.RequestId requestId) RequestId.RequestId requestId,
Values.QoS qos)
{ {
var request = await new RequestBuilder() var request = await new RequestBuilder()
.WithHttpMethod(httpMethod) .WithHttpMethod(httpMethod)
@ -26,6 +27,7 @@ namespace Ocelot.Request.Builder
.WithHeaders(headers) .WithHeaders(headers)
.WithRequestId(requestId) .WithRequestId(requestId)
.WithCookies(cookies) .WithCookies(cookies)
.WithQos(qos)
.Build(); .Build();
return new OkResponse<Request>(request); return new OkResponse<Request>(request);

View File

@ -14,6 +14,7 @@ namespace Ocelot.Request.Builder
IRequestCookieCollection cookies, IRequestCookieCollection cookies,
QueryString queryString, QueryString queryString,
string contentType, string contentType,
RequestId.RequestId requestId); RequestId.RequestId requestId,
Values.QoS qos);
} }
} }

View File

@ -22,6 +22,7 @@ namespace Ocelot.Request.Builder
private RequestId.RequestId _requestId; private RequestId.RequestId _requestId;
private IRequestCookieCollection _cookies; private IRequestCookieCollection _cookies;
private readonly string[] _unsupportedHeaders = {"host"}; private readonly string[] _unsupportedHeaders = {"host"};
private Values.QoS _qos;
public RequestBuilder WithHttpMethod(string httpMethod) public RequestBuilder WithHttpMethod(string httpMethod)
{ {
@ -71,6 +72,12 @@ namespace Ocelot.Request.Builder
return this; return this;
} }
public RequestBuilder WithQos(Values.QoS qos)
{
_qos = qos;
return this;
}
public async Task<Request> Build() public async Task<Request> Build()
{ {
var uri = CreateUri(); var uri = CreateUri();
@ -90,7 +97,7 @@ namespace Ocelot.Request.Builder
var cookieContainer = CreateCookieContainer(uri); var cookieContainer = CreateCookieContainer(uri);
return new Request(httpRequestMessage, cookieContainer); return new Request(httpRequestMessage, cookieContainer, _qos);
} }
private Uri CreateUri() private Uri CreateUri()

View File

@ -32,7 +32,8 @@ namespace Ocelot.Request.Middleware
var buildResult = await _requestCreator var buildResult = await _requestCreator
.Build(context.Request.Method, DownstreamUrl, context.Request.Body, .Build(context.Request.Method, DownstreamUrl, context.Request.Body,
context.Request.Headers, context.Request.Cookies, context.Request.QueryString, context.Request.Headers, context.Request.Cookies, context.Request.QueryString,
context.Request.ContentType, new RequestId.RequestId(DownstreamRoute?.ReRoute?.RequestIdKey, context.TraceIdentifier)); context.Request.ContentType, new RequestId.RequestId(DownstreamRoute?.ReRoute?.RequestIdKey, context.TraceIdentifier),
new Values.QoS(DownstreamRoute.ReRoute.ExceptionsAllowedBeforeBreaking, DownstreamRoute.ReRoute.DurationOfBreak, DownstreamRoute.ReRoute.TimeoutValue));
if (buildResult.IsError) if (buildResult.IsError)
{ {

View File

@ -1,17 +1,20 @@
using System.Net; using Ocelot.Values;
using System.Net;
using System.Net.Http; using System.Net.Http;
namespace Ocelot.Request namespace Ocelot.Request
{ {
public class Request public class Request
{ {
public Request(HttpRequestMessage httpRequestMessage, CookieContainer cookieContainer) public Request(HttpRequestMessage httpRequestMessage, CookieContainer cookieContainer, QoS qos)
{ {
HttpRequestMessage = httpRequestMessage; HttpRequestMessage = httpRequestMessage;
CookieContainer = cookieContainer; CookieContainer = cookieContainer;
Qos = qos;
} }
public HttpRequestMessage HttpRequestMessage { get; private set; } public HttpRequestMessage HttpRequestMessage { get; private set; }
public CookieContainer CookieContainer { get; private set; } public CookieContainer CookieContainer { get; private set; }
public QoS Qos { get; private set; }
} }
} }

View File

@ -0,0 +1,74 @@
using Ocelot.Logging;
using Polly;
using Polly.CircuitBreaker;
using Polly.Timeout;
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace Ocelot.Requester
{
public class CircuitBreakingDelegatingHandler : DelegatingHandler
{
private readonly IOcelotLogger _logger;
private readonly int _exceptionsAllowedBeforeBreaking;
private readonly TimeSpan _durationOfBreak;
private readonly Policy _circuitBreakerPolicy;
private readonly TimeoutPolicy _timeoutPolicy;
public CircuitBreakingDelegatingHandler(int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak,TimeSpan timeoutValue
,TimeoutStrategy timeoutStrategy, IOcelotLogger logger, HttpMessageHandler innerHandler)
: base(innerHandler)
{
this._exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
this._durationOfBreak = durationOfBreak;
_circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.Or<TimeoutRejectedException>()
.Or<TimeoutException>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: exceptionsAllowedBeforeBreaking,
durationOfBreak: durationOfBreak,
onBreak: (ex, breakDelay) =>
{
_logger.LogError(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
},
onReset: () => _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."),
onHalfOpen: () => _logger.LogDebug(".Breaker logging: Half-open; next call is a trial.")
);
_timeoutPolicy = Policy.TimeoutAsync(timeoutValue, timeoutStrategy);
_logger = logger;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Task<HttpResponseMessage> responseTask = null;
try
{
responseTask = Policy.WrapAsync(_circuitBreakerPolicy, _timeoutPolicy).ExecuteAsync<HttpResponseMessage>(() =>
{
return base.SendAsync(request,cancellationToken);
});
return responseTask;
}
catch (BrokenCircuitException ex)
{
_logger.LogError($"Reached to allowed number of exceptions. Circuit is open. AllowedExceptionCount: {_exceptionsAllowedBeforeBreaking}, DurationOfBreak: {_durationOfBreak}",ex);
throw;
}
catch (HttpRequestException)
{
return responseTask;
}
}
private static bool IsTransientFailure(HttpResponseMessage result)
{
return result.StatusCode >= HttpStatusCode.InternalServerError;
}
}
}

View File

@ -0,0 +1,41 @@
using Ocelot.Logging;
using Ocelot.Values;
using Polly.Timeout;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace Ocelot.Requester
{
internal class HttpClientBuilder
{
private readonly Dictionary<int, Func<DelegatingHandler>> handlers = new Dictionary<int, Func<DelegatingHandler>>();
public HttpClientBuilder WithCircuitBreaker(QoS qos, IOcelotLogger logger, HttpMessageHandler innerHandler)
{
handlers.Add(5000, () => new CircuitBreakingDelegatingHandler(qos.ExceptionsAllowedBeforeBreaking, qos.DurationOfBreak, qos.TimeoutValue, qos.TimeoutStrategy, logger, innerHandler));
return this;
}
internal HttpClient Build()
{
return handlers.Any() ? new HttpClient(CreateHttpMessageHandler()) : new HttpClient();
}
private HttpMessageHandler CreateHttpMessageHandler()
{
HttpMessageHandler httpMessageHandler = new HttpClientHandler();
handlers.OrderByDescending(handler => handler.Key).Select(handler => handler.Value).Reverse().ToList().ForEach(handler =>
{
var delegatingHandler = handler();
delegatingHandler.InnerHandler = httpMessageHandler;
httpMessageHandler = delegatingHandler;
});
return httpMessageHandler;
}
}
}

View File

@ -4,9 +4,6 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.Responses; using Ocelot.Responses;
using Polly;
using Polly.Timeout;
using Polly.CircuitBreaker;
using Ocelot.Logging; using Ocelot.Logging;
namespace Ocelot.Requester namespace Ocelot.Requester
@ -22,40 +19,19 @@ namespace Ocelot.Requester
public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request) public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
{ {
double timeoutvalue = 5000; HttpClientBuilder builder = new HttpClientBuilder();
TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic;
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromMilliseconds(timeoutvalue), timeoutStrategy);
var circuitBreakerPolicy = Policy
.Handle<Exception>()
.Or<TimeoutRejectedException>()
.Or<TimeoutException>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: 4,
durationOfBreak: TimeSpan.FromSeconds(8),
onBreak: (ex, breakDelay) =>
{
_logger.LogError(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
},
onReset: () => _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."),
onHalfOpen: () => _logger.LogDebug(".Breaker logging: Half-open; next call is a trial.")
);
using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer }) using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer })
using (var httpClient = new HttpClient(handler)) {
builder.WithCircuitBreaker(request.Qos, _logger, handler);
using (var httpClient = builder.Build())
{ {
try try
{ {
// Retry the following call according to the policy - 3 times. var response = await httpClient.SendAsync(request.HttpRequestMessage);
HttpResponseMessage response = await Policy.WrapAsync(circuitBreakerPolicy, timeoutPolicy).ExecuteAsync<HttpResponseMessage>(() =>
{
return httpClient.SendAsync(request.HttpRequestMessage);
});
return new OkResponse<HttpResponseMessage>(response); return new OkResponse<HttpResponseMessage>(response);
} }
catch (BrokenCircuitException exception) catch (Exception exception)
{ {
return return
new ErrorResponse<HttpResponseMessage>(new List<Error> new ErrorResponse<HttpResponseMessage>(new List<Error>
@ -66,4 +42,5 @@ namespace Ocelot.Requester
} }
} }
} }
}
} }

View File

@ -7,5 +7,7 @@ namespace Ocelot.Requester
public interface IHttpRequester public interface IHttpRequester
{ {
Task<Response<HttpResponseMessage>> GetResponse(Request.Request request); Task<Response<HttpResponseMessage>> GetResponse(Request.Request request);
} }
} }

27
src/Ocelot/Values/QoS.cs Normal file
View File

@ -0,0 +1,27 @@
using Polly.Timeout;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ocelot.Values
{
public class QoS
{
public QoS(int exceptionsAllowedBeforeBreaking, int durationofBreak, int timeoutValue, TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
{
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
DurationOfBreak = TimeSpan.FromMilliseconds(durationofBreak);
TimeoutValue = TimeSpan.FromMilliseconds(timeoutValue);
TimeoutStrategy = timeoutStrategy;
}
public int ExceptionsAllowedBeforeBreaking { get; private set; }
public TimeSpan DurationOfBreak { get; private set; }
public TimeSpan TimeoutValue { get; private set; }
public TimeoutStrategy TimeoutStrategy { get; private set; }
}
}

View File

@ -125,6 +125,9 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AdditionalScopes = new List<string>(), AdditionalScopes = new List<string>(),
@ -165,6 +168,9 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = "Post",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AdditionalScopes = new List<string>(), AdditionalScopes = new List<string>(),
@ -205,6 +211,9 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = "Post",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AdditionalScopes = new List<string>(), AdditionalScopes = new List<string>(),

View File

@ -43,6 +43,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AdditionalScopes = new List<string>(), AdditionalScopes = new List<string>(),

View File

@ -37,6 +37,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
FileCacheOptions = new FileCacheOptions FileCacheOptions = new FileCacheOptions
{ {
TtlSeconds = 100 TtlSeconds = 100
@ -73,6 +76,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
FileCacheOptions = new FileCacheOptions FileCacheOptions = new FileCacheOptions
{ {
TtlSeconds = 1 TtlSeconds = 1

View File

@ -35,7 +35,10 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/products/{productId}", UpstreamTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get" UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000
} }
} }
}; };
@ -63,7 +66,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/products/{productId}", UpstreamTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = false ReRouteIsCaseSensitive = false,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -91,7 +97,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/products/{productId}", UpstreamTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true ReRouteIsCaseSensitive = true,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000
} }
} }
}; };
@ -119,7 +128,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/PRODUCTS/{productId}", UpstreamTemplate = "/PRODUCTS/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true ReRouteIsCaseSensitive = true,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -147,7 +159,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/products/{productId}", UpstreamTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true ReRouteIsCaseSensitive = true,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -175,7 +190,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/PRODUCTS/{productId}", UpstreamTemplate = "/PRODUCTS/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true ReRouteIsCaseSensitive = true,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000
} }
} }
}; };

View File

@ -57,6 +57,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AdditionalScopes = new List<string> AdditionalScopes = new List<string>

View File

@ -57,6 +57,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AdditionalScopes = new List<string> AdditionalScopes = new List<string>

View File

@ -51,6 +51,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -88,6 +91,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -125,6 +131,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -162,6 +171,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -199,6 +211,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -236,6 +251,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };

View File

@ -39,7 +39,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
RequestIdKey = _steps.RequestIdKey RequestIdKey = _steps.RequestIdKey,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -67,7 +70,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
RequestIdKey = _steps.RequestIdKey RequestIdKey = _steps.RequestIdKey,
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -97,6 +103,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
}, },
GlobalConfiguration = new FileGlobalConfiguration GlobalConfiguration = new FileGlobalConfiguration

View File

@ -46,6 +46,9 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -74,6 +77,9 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -102,6 +108,9 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -130,6 +139,9 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/products/", UpstreamTemplate = "/products/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -158,6 +170,9 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/products", UpstreamTemplate = "/products",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -186,6 +201,9 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/products/{productId}", UpstreamTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -212,7 +230,10 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamTemplate = "/products/{productId}", UpstreamTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get" UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -240,7 +261,10 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
DownstreamScheme = "http", DownstreamScheme = "http",
UpstreamTemplate = "/", UpstreamTemplate = "/",
UpstreamHttpMethod = "Post" UpstreamHttpMethod = "Post",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };
@ -269,6 +293,9 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamHttpMethod = "Get", UpstreamHttpMethod = "Get",
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak =5,
TimeoutValue = 5000,
} }
} }
}; };

View File

@ -1 +1 @@
{"ReRoutes":[{"DownstreamPathTemplate":"/","UpstreamTemplate":"/","UpstreamHttpMethod":"Get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"http","DownstreamHost":"localhost","DownstreamPort":41879}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":null,"Address":null}}} {"ReRoutes":[{"DownstreamPathTemplate":"/","UpstreamTemplate":"/","UpstreamHttpMethod":"Get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"http","DownstreamHost":"localhost","DownstreamPort":41879,"ExceptionsAllowedBeforeBreaking":3,"DurationOfBreak":5,"TimeoutValue":5000}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":null,"Address":null}}}

View File

@ -7,6 +7,9 @@
"DownstreamPort": 52876, "DownstreamPort": 52876,
"UpstreamTemplate": "/identityserverexample", "UpstreamTemplate": "/identityserverexample",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"AuthenticationOptions": { "AuthenticationOptions": {
"Provider": "IdentityServer", "Provider": "IdentityServer",
"ProviderRootUrl": "http://localhost:52888", "ProviderRootUrl": "http://localhost:52888",
@ -47,6 +50,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts", "UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -55,7 +61,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}", "UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Get" "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/posts/{postId}/comments", "DownstreamPathTemplate": "/posts/{postId}/comments",
@ -63,7 +72,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}/comments", "UpstreamTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": "Get" "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/comments", "DownstreamPathTemplate": "/comments",
@ -71,7 +83,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/comments", "UpstreamTemplate": "/comments",
"UpstreamHttpMethod": "Get" "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/posts", "DownstreamPathTemplate": "/posts",
@ -79,7 +94,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts", "UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Post" "UpstreamHttpMethod": "Post",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/posts/{postId}", "DownstreamPathTemplate": "/posts/{postId}",
@ -87,7 +105,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}", "UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Put" "UpstreamHttpMethod": "Put",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/posts/{postId}", "DownstreamPathTemplate": "/posts/{postId}",
@ -95,7 +116,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}", "UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Patch" "UpstreamHttpMethod": "Patch",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/posts/{postId}", "DownstreamPathTemplate": "/posts/{postId}",
@ -103,7 +127,10 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}", "UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Delete" "UpstreamHttpMethod": "Delete",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}, },
{ {
"DownstreamPathTemplate": "/api/products", "DownstreamPathTemplate": "/api/products",
@ -112,6 +139,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/products", "UpstreamTemplate": "/products",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -130,6 +160,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/products", "UpstreamTemplate": "/products",
"UpstreamHttpMethod": "Post", "UpstreamHttpMethod": "Post",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -139,6 +172,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/products/{productId}", "UpstreamTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Put", "UpstreamHttpMethod": "Put",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -148,6 +184,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/products/{productId}", "UpstreamTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Delete", "UpstreamHttpMethod": "Delete",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -157,6 +196,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/customers", "UpstreamTemplate": "/customers",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -166,6 +208,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}", "UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -175,6 +220,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/customers", "UpstreamTemplate": "/customers",
"UpstreamHttpMethod": "Post", "UpstreamHttpMethod": "Post",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -184,6 +232,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}", "UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Put", "UpstreamHttpMethod": "Put",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -193,6 +244,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}", "UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Delete", "UpstreamHttpMethod": "Delete",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -202,6 +256,9 @@
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamTemplate": "/posts/", "UpstreamTemplate": "/posts/",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
} }
], ],

View File

@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Request
this.Given(x => x.GivenTheDownStreamUrlIs("any old string")) this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), new CookieContainer()))) .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), new CookieContainer(),new Values.QoS(3, 8 ,5000, Polly.Timeout.TimeoutStrategy.Pessimistic))))
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
.BDDfy(); .BDDfy();
@ -91,7 +91,7 @@ namespace Ocelot.UnitTests.Request
_request = new OkResponse<Ocelot.Request.Request>(request); _request = new OkResponse<Ocelot.Request.Request>(request);
_requestBuilder _requestBuilder
.Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<IHeaderDictionary>(), .Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<IHeaderDictionary>(),
It.IsAny<IRequestCookieCollection>(), It.IsAny<QueryString>(), It.IsAny<string>(), It.IsAny<Ocelot.RequestId.RequestId>())) It.IsAny<IRequestCookieCollection>(), It.IsAny<QueryString>(), It.IsAny<string>(), It.IsAny<Ocelot.RequestId.RequestId>(),It.IsAny<Values.QoS>()))
.ReturnsAsync(_request); .ReturnsAsync(_request);
} }

View File

@ -25,6 +25,7 @@ namespace Ocelot.UnitTests.Request
private readonly IRequestCreator _requestCreator; private readonly IRequestCreator _requestCreator;
private Response<Ocelot.Request.Request> _result; private Response<Ocelot.Request.Request> _result;
private Ocelot.RequestId.RequestId _requestId; private Ocelot.RequestId.RequestId _requestId;
private Ocelot.Values.QoS _qos;
public RequestBuilderTests() public RequestBuilderTests()
{ {
@ -37,6 +38,7 @@ namespace Ocelot.UnitTests.Request
{ {
this.Given(x => x.GivenIHaveHttpMethod("GET")) this.Given(x => x.GivenIHaveHttpMethod("GET"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x=> x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectDownstreamUrlIsUsed("http://www.bbc.co.uk/")) .And(x => x.ThenTheCorrectDownstreamUrlIsUsed("http://www.bbc.co.uk/"))
.BDDfy(); .BDDfy();
@ -47,6 +49,8 @@ namespace Ocelot.UnitTests.Request
{ {
this.Given(x => x.GivenIHaveHttpMethod("POST")) this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectHttpMethodIsUsed(HttpMethod.Post)) .And(x => x.ThenTheCorrectHttpMethodIsUsed(HttpMethod.Post))
.BDDfy(); .BDDfy();
@ -59,6 +63,8 @@ namespace Ocelot.UnitTests.Request
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom"))) .And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
.And(x => x.GivenTheContentTypeIs("application/json")) .And(x => x.GivenTheContentTypeIs("application/json"))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom"))) .And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom")))
.BDDfy(); .BDDfy();
@ -71,6 +77,8 @@ namespace Ocelot.UnitTests.Request
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom"))) .And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
.And(x => x.GivenTheContentTypeIs("application/json")) .And(x => x.GivenTheContentTypeIs("application/json"))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary .And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
{ {
@ -88,6 +96,8 @@ namespace Ocelot.UnitTests.Request
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom"))) .And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
.And(x => x.GivenTheContentTypeIs("application/json; charset=utf-8")) .And(x => x.GivenTheContentTypeIs("application/json; charset=utf-8"))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary .And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
{ {
@ -107,6 +117,8 @@ namespace Ocelot.UnitTests.Request
{ {
{"ChopSticks", "Bubbles" } {"ChopSticks", "Bubbles" }
})) }))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary .And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary
{ {
@ -124,6 +136,7 @@ namespace Ocelot.UnitTests.Request
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheHttpHeadersAre(new HeaderDictionary())) .And(x => x.GivenTheHttpHeadersAre(new HeaderDictionary()))
.And(x => x.GivenTheRequestIdIs(new Ocelot.RequestId.RequestId("RequestId", requestId))) .And(x => x.GivenTheRequestIdIs(new Ocelot.RequestId.RequestId("RequestId", requestId)))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary .And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary
{ {
@ -142,6 +155,7 @@ namespace Ocelot.UnitTests.Request
{"RequestId", "534534gv54gv45g" } {"RequestId", "534534gv54gv45g" }
})) }))
.And(x => x.GivenTheRequestIdIs(new Ocelot.RequestId.RequestId("RequestId", Guid.NewGuid().ToString()))) .And(x => x.GivenTheRequestIdIs(new Ocelot.RequestId.RequestId("RequestId", Guid.NewGuid().ToString())))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary .And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary
{ {
@ -161,6 +175,7 @@ namespace Ocelot.UnitTests.Request
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheHttpHeadersAre(new HeaderDictionary())) .And(x => x.GivenTheHttpHeadersAre(new HeaderDictionary()))
.And(x => x.GivenTheRequestIdIs(new Ocelot.RequestId.RequestId(requestIdKey, requestIdValue))) .And(x => x.GivenTheRequestIdIs(new Ocelot.RequestId.RequestId(requestIdKey, requestIdValue)))
.And(x => x.GivenTheQos(new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic)))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheRequestIdIsNotInTheHeaders()) .And(x => x.ThenTheRequestIdIsNotInTheHeaders())
.BDDfy(); .BDDfy();
@ -171,6 +186,11 @@ namespace Ocelot.UnitTests.Request
_requestId = requestId; _requestId = requestId;
} }
private void GivenTheQos(Ocelot.Values.QoS qos)
{
_qos = qos;
}
[Fact] [Fact]
public void should_use_cookies() public void should_use_cookies()
{ {
@ -281,7 +301,7 @@ namespace Ocelot.UnitTests.Request
private void WhenICreateARequest() private void WhenICreateARequest()
{ {
_result = _requestCreator.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers, _result = _requestCreator.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers,
_cookies, _query, _contentType, _requestId).Result; _cookies, _query, _contentType, _requestId, _qos).Result;
} }

View File

@ -61,7 +61,7 @@ namespace Ocelot.UnitTests.Requester
[Fact] [Fact]
public void should_call_scoped_data_repository_correctly() public void should_call_scoped_data_repository_correctly()
{ {
this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),new CookieContainer()))) this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),new CookieContainer(), new Values.QoS(3, 8, 5000, Polly.Timeout.TimeoutStrategy.Pessimistic))))
.And(x => x.GivenTheRequesterReturns(new HttpResponseMessage())) .And(x => x.GivenTheRequesterReturns(new HttpResponseMessage()))
.And(x => x.GivenTheScopedRepoReturns()) .And(x => x.GivenTheScopedRepoReturns())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())