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 _downstreamHost;
private int _dsPort;
private int _exceptionsAllowedBeforeBreaking;
private int _durationOfBreak;
private int _timeoutValue;
public ReRouteBuilder()
{
@ -192,6 +195,24 @@ namespace Ocelot.Configuration.Builder
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()
{
Func<HostAndPort> downstreamHostFunc = () => new HostAndPort(_downstreamHost, _dsPort);
@ -200,7 +221,8 @@ namespace Ocelot.Configuration.Builder
_isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName,
_requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement,
_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?.Provider);
Func<HostAndPort> downstreamHostAndPortFunc = () => new HostAndPort(reRoute.DownstreamHost.Trim('/'), reRoute.DownstreamPort);
if (isAuthenticated)
@ -116,7 +115,8 @@ namespace Ocelot.Configuration.Creator
reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries,
requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds),
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,
@ -125,7 +125,8 @@ namespace Ocelot.Configuration.Creator
reRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>(),
requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds),
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)

View File

@ -29,5 +29,8 @@ namespace Ocelot.Configuration.File
public string DownstreamScheme {get;set;}
public string DownstreamHost {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,
List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries,
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;
UpstreamTemplate = upstreamTemplate;
@ -35,6 +36,9 @@ namespace Ocelot.Configuration
ServiceDiscoveryAddress = serviceDiscoveryAddress;
DownstreamHostAndPort = downstreamHostAndPort;
DownstreamScheme = downstreamScheme;
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
DurationOfBreak = durationofBreak;
TimeoutValue = timeoutValue;
}
public DownstreamPathTemplate DownstreamPathTemplate { get; private set; }
@ -57,5 +61,8 @@ namespace Ocelot.Configuration
public string ServiceDiscoveryAddress { get; private set;}
public Func<HostAndPort> DownstreamHostAndPort {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,
QueryString queryString,
string contentType,
RequestId.RequestId requestId)
RequestId.RequestId requestId,
Values.QoS qos)
{
var request = await new RequestBuilder()
.WithHttpMethod(httpMethod)
@ -26,6 +27,7 @@ namespace Ocelot.Request.Builder
.WithHeaders(headers)
.WithRequestId(requestId)
.WithCookies(cookies)
.WithQos(qos)
.Build();
return new OkResponse<Request>(request);

View File

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

View File

@ -32,7 +32,8 @@ namespace Ocelot.Request.Middleware
var buildResult = await _requestCreator
.Build(context.Request.Method, DownstreamUrl, context.Request.Body,
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)
{

View File

@ -1,17 +1,20 @@
using System.Net;
using Ocelot.Values;
using System.Net;
using System.Net.Http;
namespace Ocelot.Request
{
public class Request
{
public Request(HttpRequestMessage httpRequestMessage, CookieContainer cookieContainer)
public Request(HttpRequestMessage httpRequestMessage, CookieContainer cookieContainer, QoS qos)
{
HttpRequestMessage = httpRequestMessage;
CookieContainer = cookieContainer;
Qos = qos;
}
public HttpRequestMessage HttpRequestMessage { 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 Ocelot.Errors;
using Ocelot.Responses;
using Polly;
using Polly.Timeout;
using Polly.CircuitBreaker;
using Ocelot.Logging;
namespace Ocelot.Requester
@ -22,46 +19,26 @@ namespace Ocelot.Requester
public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
{
double timeoutvalue = 5000;
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.")
);
HttpClientBuilder builder = new HttpClientBuilder();
using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer })
using (var httpClient = new HttpClient(handler))
{
try
builder.WithCircuitBreaker(request.Qos, _logger, handler);
using (var httpClient = builder.Build())
{
// Retry the following call according to the policy - 3 times.
HttpResponseMessage response = await Policy.WrapAsync(circuitBreakerPolicy, timeoutPolicy).ExecuteAsync<HttpResponseMessage>(() =>
try
{
return httpClient.SendAsync(request.HttpRequestMessage);
});
return new OkResponse<HttpResponseMessage>(response);
}
catch (BrokenCircuitException exception)
{
return
new ErrorResponse<HttpResponseMessage>(new List<Error>
{
new UnableToCompleteRequestError(exception)
});
var response = await httpClient.SendAsync(request.HttpRequestMessage);
return new OkResponse<HttpResponseMessage>(response);
}
catch (Exception exception)
{
return
new ErrorResponse<HttpResponseMessage>(new List<Error>
{
new UnableToCompleteRequestError(exception)
});
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -1,119 +1,149 @@
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 52876,
"UpstreamTemplate": "/identityserverexample",
"UpstreamHttpMethod": "Get",
"AuthenticationOptions": {
"Provider": "IdentityServer",
"ProviderRootUrl": "http://localhost:52888",
"ScopeName": "api",
"AdditionalScopes": [
"openid",
"offline_access"
],
"ScopeSecret": "secret"
},
"AddHeadersToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddClaimsToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddQueriesToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"RouteClaimsRequirement": {
"UserType": "registered"
},
"RequestIdKey": "OcRequestId"
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 52876,
"UpstreamTemplate": "/identityserverexample",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"AuthenticationOptions": {
"Provider": "IdentityServer",
"ProviderRootUrl": "http://localhost:52888",
"ScopeName": "api",
"AdditionalScopes": [
"openid",
"offline_access"
],
"ScopeSecret": "secret"
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
"AddHeadersToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Get"
"AddClaimsToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
{
"DownstreamPathTemplate": "/posts/{postId}/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": "Get"
"AddQueriesToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
{
"DownstreamPathTemplate": "/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/comments",
"UpstreamHttpMethod": "Get"
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Post"
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Put"
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Patch"
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Delete"
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/products",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
"RouteClaimsRequirement": {
"UserType": "registered"
},
"RequestIdKey": "OcRequestId"
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/posts/{postId}/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/comments",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts",
"UpstreamHttpMethod": "Post",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Put",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Patch",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Delete",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/products",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
@ -123,87 +153,114 @@
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/products",
"UpstreamHttpMethod": "Post",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Put",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Delete",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers",
"UpstreamHttpMethod": "Post",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Put",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Delete",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
}
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/products",
"UpstreamHttpMethod": "Post",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Put",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Delete",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers",
"UpstreamHttpMethod": "Post",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Put",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Delete",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamTemplate": "/posts/",
"UpstreamHttpMethod": "Get",
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000,
"FileCacheOptions": { "TtlSeconds": 15 }
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId"

View File

@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Request
this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
.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())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
.BDDfy();
@ -91,7 +91,7 @@ namespace Ocelot.UnitTests.Request
_request = new OkResponse<Ocelot.Request.Request>(request);
_requestBuilder
.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);
}

View File

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