public Task SetAsync(string id, RateLimitCounter counter, TimeSpan?expirationTime)
        {
            var options = new MemoryCacheEntryOptions
            {
                Priority = CacheItemPriority.NeverRemove
            };

            if (expirationTime.HasValue)
            {
                options.SetAbsoluteExpiration(expirationTime.Value);
            }

            _cache.Set(id, counter, options);

            return(Task.CompletedTask);
        }
示例#2
0
        public async Task <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 = _rateLimitStore.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 = rule.PeriodTimespan;
                    await _rateLimitStore.SetAsync(counterId, counter, TimeSpan.FromSeconds(expirationTime));
                }
                else
                {
                    await _rateLimitStore.RemoveAsync(counterId);
                }
            }
            else
            {
                var expirationTime = ConvertToTimeSpan(rule.Period);
                await _rateLimitStore.SetAsync(counterId, counter, expirationTime);
            }

            return(counter);
        }
示例#3
0
        public Task SaveRateLimitCounter(ClientRequestIdentity requestIdentity, RateLimitOptions option, RateLimitCounter counter, TimeSpan expirationTime)
        {
            var counterId = ComputeCounterKey(requestIdentity, option);

            // stores: id (string) - timestamp (datetime) - total_requests (long)
            _rateLimitStore.SetAsync(counterId, counter, expirationTime);
            return(Task.CompletedTask);
        }
 public void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
 {
     _logger.LogInformation(
         $"Request {identity.HttpVerb}:{identity.Path} from ClientId {identity.ClientId} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. TraceIdentifier {httpContext.TraceIdentifier}.");
 }