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); }
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); }
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); }
public void Set(string id, RateLimitCounter counter, TimeSpan expirationTime) { _memoryCache.Set(id, counter, new MemoryCacheEntryOptions().SetAbsoluteExpiration(expirationTime)); }
protected abstract void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule);
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}."); }
public void Set(string id, RateLimitCounter counter, TimeSpan expirationTime) { _memoryCache.SetString(id, JsonConvert.SerializeObject(counter), new DistributedCacheEntryOptions().SetAbsoluteExpiration(expirationTime)); }
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); }
protected override void LogBlockedRequest(HttpContext httpContext, AspNetCoreRateLimit.ClientRequestIdentity identity, AspNetCoreRateLimit.RateLimitCounter counter, AspNetCoreRateLimit.RateLimitRule rule) { base.LogBlockedRequest(httpContext, identity, counter, rule); }
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); } }