/// <summary> /// check a request for rate limit /// </summary> /// <param name="request">a request</param> /// <returns>the stream of check result</returns> public async Task <AlgorithmCheckResult> CheckAsync(object request, RateLimitTypeAttributeJson rateLimitAttrData) { if (_updatable) { using (var l = await _mutex.ReaderLockAsync()) { var originalRuleChecks = CheckAllRulesAsync(request, rateLimitAttrData); var ruleCheckResults = new List <RuleCheckResult>(); await foreach (var result in originalRuleChecks) { ruleCheckResults.Add(result); } return(new AlgorithmCheckResult(ruleCheckResults)); } } else { var originalRuleChecks = CheckAllRulesAsync(request, rateLimitAttrData); var ruleCheckResults = new List <RuleCheckResult>(); await foreach (var result in originalRuleChecks) { ruleCheckResults.Add(result); } return(new AlgorithmCheckResult(ruleCheckResults)); } }
private IEnumerable <RuleCheckResult> CheckAllRules(object request, RateLimitTypeAttributeJson rateLimitAttrData) { // the control of traversal rules is given to the external access program foreach (var rule in _rules) { if (rule.CheckRuleMatching(request)) { var target = rule.ExtractTarget(request); if (string.IsNullOrWhiteSpace(target)) { throw new NotSupportedException("Null target is not supported"); } target = string.Concat(rule.Id, "-", target); yield return(CheckSingleRule(target, rule, rateLimitAttrData)); } } }
/// <summary> /// Check single rule for target /// </summary> /// <param name="target"></param> /// <param name="rule"></param> /// <param name="rateLimitAttrData"></param> /// <returns></returns> protected abstract Task <RuleCheckResult> CheckSingleRuleAsync(string target, RateLimitRule rule, RateLimitTypeAttributeJson rateLimitAttrData);
private async IAsyncEnumerable <RuleCheckResult> CheckAllRulesAsync(object request, RateLimitTypeAttributeJson rateLimitAttrData) { // the control of traversal rules is given to the external access program foreach (var rule in _rules) { var match = false; if (rule.CheckRuleMatchingAsync != null) { match = await rule.CheckRuleMatchingAsync(request); } else { match = rule.CheckRuleMatching(request); } if (match) { string target = string.Empty; if (rule.ExtractTargetAsync != null) { target = await rule.ExtractTargetAsync(request); } else { target = rule.ExtractTarget(request); } if (string.IsNullOrWhiteSpace(target)) { throw new NotSupportedException("Null target is not supported"); } target = string.Concat(rule.Id, "-", target); yield return(await CheckSingleRuleAsync(target, rule, rateLimitAttrData)); } } }
/// <summary> /// get method rateLimit attribute /// </summary> /// <param name="context"></param> /// <returns></returns> private static RateLimitTypeAttributeJson GetRateLimitTypeAttributeData(HttpContext context) { #region check controller of method mark TokenbucketAttribute is priority compare with global service.AddRamitLimit RateLimitTypeAttributeJson storeRule = null; if (context != null) { string target = context.Request.Path.Value; bool exists = _requestRateLimitRule.TryGetValue(target, out storeRule); if (!exists) { //check Attribute var endpoint = GetEndpoint(context); if (endpoint != null) { var actionTokenBucketAttribute = endpoint.Metadata.GetMetadata <TokenBucketLimitAttribute>(); var actionLeakyBucketAttribute = endpoint.Metadata.GetMetadata <LeakyBucketLimitAttribute>(); var actionFixedWindowAttribute = endpoint.Metadata.GetMetadata <FixedWindowLimitAttribute>(); var actionSlidingWindowAttribute = endpoint.Metadata.GetMetadata <SlidingWindowLimitAttribute>(); storeRule = actionTokenBucketAttribute != null || actionLeakyBucketAttribute != null || actionFixedWindowAttribute != null || actionSlidingWindowAttribute != null ? new RateLimitTypeAttributeJson() : null; if (actionTokenBucketAttribute != null) { storeRule.TokenBucketLimitAttribute = new TokenBucketLimitAttribute(); storeRule.TokenBucketLimitAttribute.Capacity = actionTokenBucketAttribute.Capacity; storeRule.TokenBucketLimitAttribute.InflowQuantityPerUnit = actionTokenBucketAttribute.InflowQuantityPerUnit; storeRule.TokenBucketLimitAttribute.Period = actionTokenBucketAttribute.Period; storeRule.TokenBucketLimitAttribute.RateLimitExceptionThrow = actionTokenBucketAttribute.RateLimitExceptionThrow; } if (actionLeakyBucketAttribute != null) { storeRule.LeakyBucketLimitAttribute = new LeakyBucketLimitAttribute(); storeRule.LeakyBucketLimitAttribute.Capacity = actionLeakyBucketAttribute.Capacity; storeRule.LeakyBucketLimitAttribute.OutflowQuantityPerUnit = actionLeakyBucketAttribute.OutflowQuantityPerUnit; storeRule.LeakyBucketLimitAttribute.Period = actionLeakyBucketAttribute.Period; storeRule.LeakyBucketLimitAttribute.RateLimitExceptionThrow = actionLeakyBucketAttribute.RateLimitExceptionThrow; } if (actionFixedWindowAttribute != null) { storeRule.FixedWindowLimitAttribute = new FixedWindowLimitAttribute(); storeRule.FixedWindowLimitAttribute.LimitNumber = actionFixedWindowAttribute.LimitNumber; storeRule.FixedWindowLimitAttribute.Period = actionFixedWindowAttribute.Period; storeRule.FixedWindowLimitAttribute.RateLimitExceptionThrow = actionFixedWindowAttribute.RateLimitExceptionThrow; } if (actionSlidingWindowAttribute != null) { storeRule.SlidingWindowLimitAttribute = new SlidingWindowLimitAttribute(); storeRule.SlidingWindowLimitAttribute.LimitNumber = actionSlidingWindowAttribute.LimitNumber; storeRule.SlidingWindowLimitAttribute.StatWindowPeriod = actionSlidingWindowAttribute.StatWindowPeriod; storeRule.SlidingWindowLimitAttribute.StatSmallPeriod = actionSlidingWindowAttribute.StatSmallPeriod; storeRule.SlidingWindowLimitAttribute.RateLimitExceptionThrow = actionSlidingWindowAttribute.RateLimitExceptionThrow; } if (storeRule != null) { _requestRateLimitRule.TryAdd(target, storeRule); } } } } return(storeRule); #endregion check controller of method mark TokenbucketAttribute is priority compare with global service.AddRamitLimit }