public ThrottlingStateProvider(ThrottlingConfiguration configuration, IThrottlingStateActualizer actualizer) { this.configuration = configuration; this.actualizer = actualizer; state = new ThrottlingState(); }
public void Validate(ThrottlingConfiguration configuration) { _log.Debug($"Validating {nameof(ThrottlingConfiguration)}"); if (configuration.ConcurrentRequestsLimit < 1) { throw new ArgumentOutOfRangeException(nameof(configuration.ConcurrentRequestsLimit), $"{nameof(configuration.ConcurrentRequestsLimit)} has to be greater than 0"); } if (configuration.QueueLimit < 0) { throw new ArgumentOutOfRangeException(nameof(configuration.QueueLimit), $"{nameof(configuration.QueueLimit)} has to be greater or equal to 0"); } if (configuration.QueueTimeout.TotalSeconds < 5) { throw new ArgumentOutOfRangeException(nameof(configuration.QueueTimeout), $"{nameof(configuration.QueueTimeout)} has to be greater or equal to 5"); } if (configuration.MaximumServerConnections < 1) { throw new ArgumentOutOfRangeException(nameof(configuration.MaximumServerConnections), $"{nameof(configuration.MaximumServerConnections)} has to be greater than 0"); } if (configuration.MaximumServerConnections < configuration.ConcurrentRequestsLimit + configuration.QueueLimit) { throw new ArgumentOutOfRangeException(nameof(configuration.MaximumServerConnections), $"{nameof(configuration.MaximumServerConnections)} has to be greater or equal to the sum of {nameof(configuration.ConcurrentRequestsLimit)} and {nameof(configuration.QueueLimit)}"); } _log.Info($"{nameof(ThrottlingConfiguration)} valid"); }
private static void addResetHeader(IHttpResponse response, ThrottlingConfiguration configuration, RequestCount count) { string numberOfSecondsLeftInPeriod = count != null? count.Remaining(DateTimeOffset.UtcNow).ToString(CultureInfo.InvariantCulture) : configuration.FormattedSeconds; response.AddHeader("X-Rate-Limit-Reset", numberOfSecondsLeftInPeriod); }
private static void addRemainingHeader(IHttpResponse response, ThrottlingConfiguration configuration, RequestCount count) { string numberOfRequestLeftInPeriod = count != null? count.Remaining(configuration.NumberOfRequests).ToString(CultureInfo.InvariantCulture) : configuration.FormattedRequests; response.AddHeader("X-Rate-Limit-Remaining", numberOfRequestLeftInPeriod); }
public ThrottlingMiddlewareTests() { _throttlingConfiguration = new ThrottlingConfiguration { ConcurrentRequestLimit = 5, Enabled = true, }; _cts = new CancellationTokenSource(); _httpContext.RequestAborted = _cts.Token; _httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("authenticationType", "nametype", "roletype")); _throttlingConfiguration.ExcludedEndpoints.Add(new ExcludedEndpoint { Method = "get", Path = "/health/check" }); _middleware = new Lazy <ThrottlingMiddleware>( () => new ThrottlingMiddleware( async x => { x.Response.StatusCode = 200; try { if (!int.TryParse(Regex.Match(x.Request.Path, "/duration/(\\d+)").Groups[1].Value, out var duration)) { duration = 5000; } var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token, x.RequestAborted); await Task.Delay(duration, linkedTokenSource.Token); } catch (TaskCanceledException) when(_cts.Token.IsCancellationRequested) { } catch (TaskCanceledException) when(x.RequestAborted.IsCancellationRequested) { x.Response.StatusCode = StatusCodes.Status408RequestTimeout; } }, Options.Create(_throttlingConfiguration), Options.Create(new SecurityConfiguration { Enabled = _securityEnabled }), NullLogger <ThrottlingMiddleware> .Instance)); IActionResultExecutor <ObjectResult> executor = Substitute.For <IActionResultExecutor <ObjectResult> >(); executor.ExecuteAsync(Arg.Any <ActionContext>(), Arg.Any <ObjectResult>()).ReturnsForAnyArgs(Task.CompletedTask); _collection.AddSingleton <IActionResultExecutor <ObjectResult> >(executor); _provider = _collection.BuildServiceProvider(); _httpContext.RequestServices = _provider; }
public static void Throttle(this Testing.Commons.ServiceStack.v3.HostTesterBase tester, ushort numberOfRequests, TimeSpan period) { var configuration = new ThrottlingConfiguration { NumberOfRequests = numberOfRequests, Period = period }; var manager = Substitute.For <IResourceManager>(); manager.Get(ThrottlingConfiguration.Key, Arg.Any <ThrottlingConfiguration>()) .Returns(configuration); tester.Replacing(manager); }
public async Task setup_scenario() { var throttleManager = new StubThrottleManager { Sync = new StubThrottleSync(ConcurrentRequests) }; _expectedResponse = new HttpResponseMessage(HttpStatusCode.Accepted); var baseHttpClient = new StubHttpClient(_expectedResponse); var configuration = new ThrottlingConfiguration { ThrottlePolicy = "default" }; var httpClient = baseHttpClient.AddThrottling(configuration, throttleManager); _actualResponse = await httpClient.GetAsync("/ping"); }
public void setup_scenario() { var throttleManager = new StubThrottleManager { Sync = new StubThrottleSync(ExpectedMaxConcurrentRequests) }; _baseHttpClient = new CountingHttpClient(); var configuration = new ThrottlingConfiguration { ThrottlePolicy = "default" }; var httpClient = _baseHttpClient.AddThrottling(configuration, throttleManager); var tasks = Enumerable.Range(1, ExpectedTotalRequests).Select(c => httpClient.GetAsync("/ping")).ToArray(); Task.WhenAll(tasks).Wait(5000); }
public void TestSetup() { essentials = new ThrottlingEssentials { RefreshPeriod = TimeSpan.Zero }; configuration = new ThrottlingConfigurationBuilder() .SetEssentials(() => essentials) .Build(); actualizer = Substitute.For <IThrottlingStateActualizer>(); provider = new ThrottlingStateProvider(configuration, actualizer); state = provider.ObtainState(); actualizer.ClearReceivedCalls(); }
public void Rate(IHttpRequest request, IHttpResponse response) { ApiKey apiKey = ApiKey.ExtractFrom(request); if (!apiKey.IsMissing) { var resources = request.TryResolve <IResourceManager>(); ThrottlingConfiguration configuration = resources.Get(ThrottlingConfiguration.Key, ThrottlingConfiguration.Empty()); var repository = request.TryResolve <IRequestCountRepository>(); RequestCount count = repository.Get(apiKey); addLimitHeader(response, configuration); addRemainingHeader(response, configuration, count); addResetHeader(response, configuration, count); } }
public ThrottlingMiddlewareTests() { _cts = new CancellationTokenSource(); _httpContext.RequestAborted = _cts.Token; var throttlingConfiguration = new ThrottlingConfiguration { ConcurrentRequestLimit = 5, }; throttlingConfiguration.ExcludedEndpoints.Add("get:/health/check"); _middleware = new ThrottlingMiddleware( async x => { x.Response.StatusCode = 200; await Task.Delay(5000, _cts.Token); }, Options.Create(throttlingConfiguration), NullLogger<ThrottlingMiddleware>.Instance); }
private void Init(bool securityEnabled) { _cts = new CancellationTokenSource(); _httpContext.RequestAborted = _cts.Token; _httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("authenticationType", "nametype", "roletype")); var throttlingConfiguration = new ThrottlingConfiguration { ConcurrentRequestLimit = 5, }; throttlingConfiguration.ExcludedEndpoints.Add(new ExcludedEndpoint { Method = "get", Path = "/health/check" }); _middleware = new ThrottlingMiddleware( async x => { x.Response.StatusCode = 200; try { await Task.Delay(5000, _cts.Token); } catch (TaskCanceledException) when(_cts.Token.IsCancellationRequested) { } }, Options.Create(throttlingConfiguration), Options.Create(new Microsoft.Health.Fhir.Core.Configs.SecurityConfiguration { Enabled = securityEnabled }), NullLogger <ThrottlingMiddleware> .Instance); _executor = Substitute.For <IActionResultExecutor <ObjectResult> >(); _executor.ExecuteAsync(Arg.Any <ActionContext>(), Arg.Any <ObjectResult>()).ReturnsForAnyArgs(Task.CompletedTask); _collection.AddSingleton <IActionResultExecutor <ObjectResult> >(_executor); _provider = _collection.BuildServiceProvider(); _httpContext.RequestServices = _provider; }
public static IRequestCountRepository SetupThrottling(this Testing.Commons.ServiceStack.v3.HostTesterBase tester, ushort numberOfRequests, TimeSpan period, RequestCount count = null) { var configuration = new ThrottlingConfiguration { NumberOfRequests = numberOfRequests, Period = period }; var manager = Substitute.For <IResourceManager>(); manager.Get(ThrottlingConfiguration.Key, Arg.Any <ThrottlingConfiguration>()) .Returns(configuration); tester.Replacing(manager); var repository = Substitute.For <IRequestCountRepository>(); if (count != null) { repository.Get(Arg.Any <ApiKey>()).Returns(count); } tester.Replacing(repository); return(repository); }
public void Throttle(IHttpRequest request, IHttpResponse response) { var resources = request.TryResolve <IResourceManager>(); ThrottlingConfiguration configuration = resources.Get(ThrottlingConfiguration.Key, ThrottlingConfiguration.Empty()); var key = ApiKey.ExtractFrom(request); if (!key.IsMissing && configuration.ThrottlingEnabled) { var repository = request.TryResolve <IRequestCountRepository>(); RequestCount count = repository.Ensure(key, () => new RequestCount(configuration.Period)); if (count.IsLessThan(configuration.NumberOfRequests)) { repository.Update(key, count.Increase()); } else { response.AddHeader("Retry-After", configuration.FormattedSeconds); throw new HttpError(429, configuration.ErrorMessage()); } } }
public ThrottlingMiddleware(RequestDelegate next, ThrottlingConfiguration throttlingConfiguration) { _next = next ?? throw new ArgumentNullException(nameof(next)); _capacityGuard = new ThrottlingCapacityGuard(throttlingConfiguration); }
private static void addLimitHeader(IHttpResponse response, ThrottlingConfiguration configuration) { string numberOfRequestsAllowedInPeriod = configuration.FormattedRequests; response.AddHeader("X-Rate-Limit-Limit", numberOfRequestsAllowedInPeriod); }
public ThrottlingStateProvider(ThrottlingConfiguration configuration) : this(configuration, new ThrottlingStateActualizer(configuration)) { }
public ThrottlingCapacityGuard(ThrottlingConfiguration throttlingConfiguration) { this._throttlingConfiguration = throttlingConfiguration; }
public ThrottlingProvider([NotNull] ThrottlingConfiguration configuration) : this(new ThrottlingStateProvider(configuration ?? throw new ArgumentNullException(nameof(configuration))), configuration.ErrorCallback)
public ThrottlingMiddleware(RequestDelegate next, IOptions <ThrottlingConfiguration> configuration, ILogger <ThrottlingMiddleware> logger) { _next = EnsureArg.IsNotNull(next, nameof(next)); _logger = EnsureArg.IsNotNull(logger, nameof(logger)); _configuration = EnsureArg.IsNotNull(configuration?.Value, nameof(configuration)); }
public ThrottlingStateActualizer(ThrottlingConfiguration configuration) => this.configuration = configuration;