private async Task <bool> RevertIfRequired(RateLimitingResult rateLimitingResult, HttpActionContext context, RateLimitingRequest request, RateLimitPolicy policy, Decision decision) { if (decision == Decision.REVERTSUCCESSCOST && rateLimitingResult.State == ResultState.Success) { await _rateLimiter.LimitRequestAsync(request, () => RateLimitingFilter.GetCustomAttributes(context), context.Request.Headers.Host, getPolicyFuncAsync : _ => Task.FromResult(policy), onPostLimitFuncAsync : async(rateLimitingRequest, postPolicy, rateLimitingRevertResult) => { if (rateLimitingRevertResult.State == ResultState.Success) { context.Request.Properties[$"RateLimitingResult_{_filterId}"] = rateLimitingRevertResult; } if (OnPostLimitRevert != null) { await OnPostLimitRevert.Invoke(request, postPolicy, rateLimitingRevertResult, context).ConfigureAwait(false); } }, revert : true).ConfigureAwait(false); return(await Task.FromResult(true)); } return(await Task.FromResult(false)); }
public List <RateLimitPolicy> GetPolicys() { var result = new List <RateLimitPolicy>(); using (var connection = new MySqlConnection(_mySqlOptions.ConnectionString)) { var sql = @"SELECT * FROM `ratelimit_item` where Type=3 and Prefix=@Prefix; SELECT t2.* From `ratelimit_item` t1 inner join `ratelimit_rule` t2 on t1.Id=t2.PolicyId where t1.Type=3 and t1.Prefix=@Prefix"; var multi = connection.QueryMultiple(sql, new { Prefix = _options.RateLimitCounterPrefix }); var items = multi.Read <Entities.RateLimitItem>(); var rules = multi.Read <Entities.RateLimitRule>(); if (items != null && items.AsList().Count > 0) { foreach (var item in items.AsList()) { var policy = new RateLimitPolicy(); policy.Prefix = item.Prefix; policy.PolicyType = (RateLimitPolicyType)item.PolicyType; policy.Value = item.Value; policy.Rules = new List <Models.RateLimitRule>(); rules.Where(x => x.PolicyId == item.Id).AsList().ForEach(x => { policy.Rules.Add(new Models.RateLimitRule() { Endpoint = x.Endpoint, Period = x.Period, Limit = x.Limit }); }); result.Add(policy); } } } return(result); }
public RateLimitResult Process(ClientRequestIdentity clientRequestIdentity, RateLimitPolicy rateLimitPolicy, CancellationToken cancellationToken) { if (clientRequestIdentity == null) { throw new ArgumentNullException(nameof(clientRequestIdentity)); } if (rateLimitPolicy == null) { return(RateLimitResult.NoLimit("no rate limit policy.")); } if (rateLimitPolicy.ClientIsRequired && string.IsNullOrWhiteSpace(clientRequestIdentity.ClientId)) { return(RateLimitResult.Limited("client id is required.")); } if (rateLimitPolicy.IsWhitelisted(clientRequestIdentity, out RateLimitNameListPolicyMatchedResult result)) { return(RateLimitResult.NoLimit(result.ToString())); } var matchedRules = rateLimitPolicy.GetMatchedRules(clientRequestIdentity); if (matchedRules != null && matchedRules.Any()) { lock (o_lock) { var rulesDict = new Dictionary <string, Tuple <RateLimitRule, RateLimitCounter> >(); foreach (var rule in matchedRules) { if (rule.Limit > 0) { var counterKey = ComputeCounterKey(rule); var counter = GetCounter(counterKey, rule); // check if key expired if (counter.Timestamp + rule.PeriodTimespan.Value < DateTime.UtcNow) { continue; } // check if limit is reached if (counter.Count > rule.Limit) { return(RateLimitResult.Limited(rule.ToString())); } rulesDict.Add(counterKey, Tuple.Create(rule, counter)); } else { return(RateLimitResult.Limited(rule.ToString())); } } if (rulesDict.Any()) { foreach (var item in rulesDict) { _rateLimitCounterHandler.Set(item.Key, item.Value.Item2, item.Value.Item1.PeriodTimespan.Value); } } } } return(RateLimitResult.Default); }
public BattleriteClient Build(string token) { if (rateLimitPolicy == default(IRateLimitPolicy)) { rateLimitPolicy = new RateLimitPolicy(); } var jsonSerializerSettings = new JsonApiSerializerSettings(); var requestUrlBuilder = new RequestUrlBuilder(EndPoints.BaseUrl, new List <IParameter>()); var httpClient = new HttpClient(); SetupHttpClient(token, httpClient); var requester = new Requester.Requester(httpClient, rateLimitPolicy); return(CreateBattleriteClient( CreateOrGetAssetClient(), CreateOrGetPlayerClient( jsonSerializerSettings, requestUrlBuilder, requester, CreateOrGetAssetClient()), CreateOrGetMatchClient(requestUrlBuilder, requester))); }
public void ShouldParseFourPoliciesFromOptionsCorrectly() { var rateLimitingOptions = new RateLimitingOptions() { RateLimitPolicyStrings = new List <string>() { "*:GET:api/globallylimited/{id}:5_PerMinute&8_PerHour:true:StaticPolicy_0", "*:*:/api/globallylimited/{id}/sub/{subid}:2_PerMinute:true:StaticPolicy_1", "*:*:*:100_PerMinute:true:StaticPolicy_2" }, RateLimitPolicyOptions = new List <RateLimitingPolicyOptions>() { new RateLimitingPolicyOptions() { RouteTemplate = "api/globallylimited", AllowAttributeOverride = true, AllowedCallRates = new Dictionary <string, int>() { { RateLimitUnit.PerMinute.ToString(), 3 } }, HttpMethod = "POST", Name = "GlobalPostRate" } } }; var policies = rateLimitingOptions.RateLimitPolicies; var rateLimitPolicies = policies as RateLimitPolicy[] ?? policies.ToArray(); Assert.Equal(4, rateLimitPolicies.Count()); var policy0 = new RateLimitPolicy("*", "api/globallylimited/{id}", "GET", new List <AllowedConsumptionRate>() { new AllowedConsumptionRate(5, RateLimitUnit.PerMinute), new AllowedConsumptionRate(8, RateLimitUnit.PerHour) }, true, "StaticPolicy_0"); var policy1 = new RateLimitPolicy("*", "/api/globallylimited/{id}/sub/{subid}", "*", new List <AllowedConsumptionRate>() { new AllowedConsumptionRate(2, RateLimitUnit.PerMinute) }, true, "StaticPolicy_1"); var policy2 = new RateLimitPolicy("*", "*", "*", new List <AllowedConsumptionRate>() { new AllowedConsumptionRate(100, RateLimitUnit.PerMinute) }, true, "StaticPolicy_2"); var policy3 = new RateLimitPolicy("*", "api/globallylimited", "POST", new List <AllowedConsumptionRate>() { new AllowedConsumptionRate(3, RateLimitUnit.PerMinute) }, true, "GlobalPostRate"); Assert.Equal(true, ContainsPolicy(policy0, rateLimitPolicies)); }
private static int GetThrottleCount(IRateLimitingCacheProvider rateLimiter, RateLimitPolicy policy, int totalNumberOfCalls, int sleepTimeInMilliSeconds) { int throttleCount = 0; for (var i = 1; i <= totalNumberOfCalls; i++) { if (rateLimiter.LimitRequestAsync(policy.RequestKey, policy.HttpMethod, "TestRateLimiting.com", policy.RouteTemplate, policy.AllowedCallRates).Result.Throttled) { throttleCount++; } Thread.Sleep(sleepTimeInMilliSeconds); } return(throttleCount); }
private static async Task <PoliciesValidationModel> GetPoliciesValidationModel( string folderPath, IEnumerable <CustomPolicy> customPolicies, RateLimitPolicy rateLimitPolicy) { var rateLimitPolicyToValidate = rateLimitPolicy == null ? null : new RateLimitPolicyValidationModel(rateLimitPolicy.Name, rateLimitPolicy.Calls, rateLimitPolicy.RenewalPeriod); var customPoliciesToValidate = customPolicies == null ? Enumerable.Empty <CustomPolicyValidationModel>() : await Task.WhenAll(customPolicies.Select(async cp => { using var xmlFs = new FileStream(Path.Combine(folderPath, cp.XmlFile), FileMode.Open, FileAccess.Read); using var sr = new StreamReader(xmlFs); return(new CustomPolicyValidationModel(cp.Name, await sr.ReadToEndAsync().ConfigureAwait(false))); })).ConfigureAwait(false); return(new PoliciesValidationModel(customPoliciesToValidate, rateLimitPolicyToValidate)); }
private static bool ContainsPolicy(RateLimitPolicy expectedPolicy, IEnumerable <RateLimitPolicy> policies) { return(policies.Any(policy => policy.Key.Equals(expectedPolicy.Key) && policy.AllowAttributeOverride == expectedPolicy.AllowAttributeOverride && policy.Name == expectedPolicy.Name && policy.AllowedCallRates.All(expectedPolicy.AllowedCallRates.Contains))); }
private async Task CreateOrUpdatePolicies( IGatewayClient client, Guid subscriptionId, Guid?entityId, string folderPath, PoliciesValidationResult policiesResults, string entityType, RateLimitPolicy rateLimitPolicy, IEnumerable <CustomPolicy> customPolicies) { if (entityId.HasValue) { if (rateLimitPolicy != null) { var rateLimitPolicyRequest = new RateLimitPolicyRequest( rateLimitPolicy.Name, entityId, entityType, rateLimitPolicy.Description, rateLimitPolicy.Calls, rateLimitPolicy.RenewalPeriod); switch (policiesResults.RateLimitPolicy.Status) { case ValidationStatus.CanBeCreated: var created = await client.CreateRateLimitPolicyAsync(subscriptionId, rateLimitPolicyRequest).ConfigureAwait(false); this.publishResults.Add(new GatewayAutomationResult() { ResultCode = ResultCode.RateLimitPolicyCreated, EntityId = created.Id }); break; case ValidationStatus.CanBeUpdated: var updated = await client.UpdateRateLimitPolicyAsync(subscriptionId, policiesResults.RateLimitPolicy.EntityId.Value, rateLimitPolicyRequest).ConfigureAwait(false); this.publishResults.Add(new GatewayAutomationResult() { ResultCode = ResultCode.RateLimitPolicyUpdated, EntityId = updated.Id }); break; default: throw new NotSupportedException("Unsupported RateLimitPolicy ValidationStatus in CreateOrUpdatePolicies"); } } if (customPolicies != null) { foreach (var customPolicy in customPolicies) { var customPolicyResult = policiesResults.CustomPolicies.Single(cp => string.Equals(cp.Name, customPolicy.Name, StringComparison.OrdinalIgnoreCase)); using var sr = new StreamReader(Path.Combine(folderPath, customPolicy.XmlFile)); var xmlContent = await sr.ReadToEndAsync().ConfigureAwait(false); var customPolicyRequest = new CustomPolicyRequest(customPolicy.Name, xmlContent, entityId, customPolicy.Description, entityType); switch (customPolicyResult.Status) { case ValidationStatus.CanBeCreated: var created = await client.CreateCustomPolicyAsync(subscriptionId, customPolicyRequest).ConfigureAwait(false); this.publishResults.Add(new GatewayAutomationResult() { ResultCode = ResultCode.CustomPolicyCreated, EntityId = created.Id }); break; case ValidationStatus.CanBeUpdated: var updated = await client.UpdateCustomPolicyAsync(subscriptionId, customPolicyResult.EntityId.Value, customPolicyRequest).ConfigureAwait(false); this.publishResults.Add(new GatewayAutomationResult() { ResultCode = ResultCode.CustomPolicyUpdated, EntityId = updated.Id }); break; default: throw new NotSupportedException("Unsupported CustomPolicy ValidationStatus in CreateOrUpdatePolicies"); } } } } }
public BattleriteClientBuilder WithRateLimitPolicy(RateLimitPolicy rateLimitPolicy) { this.rateLimitPolicy = rateLimitPolicy; return(this); }