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); }
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); }
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}."); }