public virtual async Task <RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default)
        {
            var counter = new RateLimitCounter
            {
                Timestamp = DateTime.UtcNow,
                Count     = 1
            };

            var counterId = BuildCounterKey(requestIdentity, rule);

            // serial reads and writes on same key
            using (await AsyncKeyLock.WriterLockAsync(counterId).ConfigureAwait(false))
            {
                var entry = await _counterStore.GetAsync(counterId, cancellationToken);

                // entry has not expired
                if (entry.HasValue && entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow)
                {
                    // increment request count
                    var totalCount = entry.Value.Count + _config.RateIncrementer?.Invoke() ?? 1;

                    // deep copy
                    counter = new RateLimitCounter
                    {
                        Timestamp = entry.Value.Timestamp,
                        Count     = totalCount
                    };
                }

                // stores: id (string) - timestamp (datetime) - total_requests (long)
                await _counterStore.SetAsync(counterId, counter, rule.PeriodTimespan.Value, cancellationToken);
            }

            return(counter);
        }
Example #2
0
        public RateLimitCounter?GetStoredRateLimitCounter(ClientRequestIdentity requestIdentity, RateLimitRule rule)
        {
            var counterId = ComputeCounterKey(requestIdentity, rule);

            // serial reads and writes
            lock (_processLocker)
            {
                var entry = _counterStore.Get(counterId);
                if (entry.HasValue)
                {
                    // entry has not expired
                    if (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow)
                    {
                        // deep copy
                        var counter = new RateLimitCounter
                        {
                            Timestamp     = entry.Value.Timestamp,
                            TotalRequests = entry.Value.TotalRequests
                        };
                        return(counter);
                    }
                }
            }
            return(null);
        }
Example #3
0
        public RateLimitCounter ProcessRequest(ClientRequestIdentity requestIdentity, RateLimitRule rule)
        {
            var counter = new RateLimitCounter
            {
                Timestamp     = DateTime.UtcNow,
                TotalRequests = 1
            };

            var counterId = ComputeCounterKey(requestIdentity, rule);

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

                        // deep copy
                        counter = new RateLimitCounter
                        {
                            Timestamp     = entry.Value.Timestamp,
                            TotalRequests = totalRequests
                        };
                    }
                }

                // stores: id (string) - timestamp (datetime) - total_requests (long)
                _counterStore.Set(counterId, counter, rule.PeriodTimespan.Value);
            }

            return(counter);
        }
Example #4
0
 public void Set(string id, RateLimitCounter counter, TimeSpan expirationTime)
 {
     _memoryCache.Set(id, counter, new MemoryCacheEntryOptions().SetAbsoluteExpiration(expirationTime));
 }
Example #5
0
 protected abstract void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule);
Example #6
0
 public virtual 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}. Blocked by rule {rule.Endpoint}, TraceIdentifier {httpContext.TraceIdentifier}.");
 }
 protected override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
 {
     _logger.LogInformation($"Request {identity.HttpVerb}:{identity.Path} from IP {identity.ClientIp} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.Count - rule.Limit}. Blocked by rule {rule.Endpoint}, TraceIdentifier {httpContext.TraceIdentifier}.");
 }
Example #8
0
 public void Set(string id, RateLimitCounter counter, TimeSpan expirationTime)
 {
     _memoryCache.SetString(id, JsonConvert.SerializeObject(counter), new DistributedCacheEntryOptions().SetAbsoluteExpiration(expirationTime));
 }
Example #9
0
 protected override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
 {
     _logger.LogInformation("Request {HttpVerb}:{Path} from ClientId {ClientId} has been blocked, quota {Limit}/{Period} exceeded by {Count}. Blocked by rule {Endpoint}, TraceIdentifier {TraceIdentifier}.", identity.HttpVerb, identity.Path, identity.ClientId, rule.Limit, rule.Period, counter.Count, rule.Endpoint, httpContext.TraceIdentifier);
 }
Example #10
0
 protected override void LogBlockedRequest(HttpContext httpContext, AspNetCoreRateLimit.ClientRequestIdentity identity, AspNetCoreRateLimit.RateLimitCounter counter, AspNetCoreRateLimit.RateLimitRule rule)
 {
     base.LogBlockedRequest(httpContext, identity, counter, rule);
 }
Example #11
0
 public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
 {
     _logger.LogInformation($"Request {identity.HttpVerb}:{identity.Path} from IP {identity.ClientIp} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule {rule.Endpoint}, TraceIdentifier {httpContext.TraceIdentifier}.");
     if (counter.TotalRequests == (rule.Limit * _options.IpFloodWarningFactor))
     {
         _logger.LogWarning($"Flood tentative from IP Address {identity.ClientIp}");
     }
     else if (counter.TotalRequests == (rule.Limit * _options.IpFloodBanFactor))
     {
         _logger.LogWarning($"Too many Flood tentative from IP Address {identity.ClientIp}");
         TempBanIP(identity.ClientIp);
     }
 }