Пример #1
0
        public RateLimitCounter ProcessRequest(ClientRequestIdentity requestIdentity, RateLimitOptions option)
        {
            RateLimitCounter counter = new RateLimitCounter(DateTime.UtcNow, 1);
            var rule = option.RateLimitRule;

            var counterId = ComputeCounterKey(requestIdentity, option);

            // serial reads and writes
            lock (_processLocker)
            {
                var entry = _counterHandler.Get(counterId);
                if (entry.HasValue)
                {
                    // entry has not expired
                    if (entry.Value.Timestamp + TimeSpan.FromSeconds(rule.PeriodTimespan) >= DateTime.UtcNow)
                    {
                        // increment request count
                        var totalRequests = entry.Value.TotalRequests + 1;

                        // deep copy
                        counter = new RateLimitCounter(entry.Value.Timestamp, totalRequests);
                    }
                }
                // stores: id (string) - timestamp (datetime) - total_requests (long)
                _counterHandler.Set(counterId, counter, TimeSpan.FromSeconds(rule.PeriodTimespan));
            }

            return(counter);
        }
Пример #2
0
        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);
        }
Пример #3
0
        public RateLimitCounter ProcessRequest(ClientRequestIdentity requestIdentity, RateLimitOptions option)
        {
            RateLimitCounter counter = new RateLimitCounter(DateTime.UtcNow, 1);
            var rule = option.RateLimitRule;

            var counterId = ComputeCounterKey(requestIdentity, option);

            // serial reads and writes
            lock (_processLocker)
            {
                var entry = _counterHandler.Get(counterId);
                if (entry.HasValue)
                {
                    // entry has not expired
                    if (entry.Value.Timestamp + TimeSpan.FromSeconds(rule.PeriodTimespan) >= DateTime.UtcNow)
                    {
                        // increment request count
                        var totalRequests = entry.Value.TotalRequests + 1;

                        // deep copy
                        counter = new RateLimitCounter(entry.Value.Timestamp, totalRequests);
                    }
                }
            }

            if (counter.TotalRequests > rule.Limit)
            {
                var retryAfter = RetryAfterFrom(counter.Timestamp, rule);
                if (retryAfter > 0)
                {
                    var expirationTime = TimeSpan.FromSeconds(rule.PeriodTimespan);
                    _counterHandler.Set(counterId, counter, expirationTime);
                }
                else
                {
                    _counterHandler.Remove(counterId);
                }
            }
            else
            {
                var expirationTime = ConvertToTimeSpan(rule.Period);
                _counterHandler.Set(counterId, counter, expirationTime);
            }

            return(counter);
        }