/// <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));
                }
            }
        }
示例#5
0
        /// <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
        }