protected RateLimitMiddleware( RequestDelegate next, RateLimitOptions options, TProcessor processor, IRateLimitConfiguration config) { _next = next; _options = options; _processor = processor; _config = config; }
protected RateLimitProcessor( RateLimitOptions options, IRateLimitCounterStore counterStore, ICounterKeyBuilder counterKeyBuilder, IRateLimitConfiguration config) { _options = options; _counterStore = counterStore; _counterKeyBuilder = counterKeyBuilder; _config = config; }
protected virtual string BuildCounterKey(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions) { var key = counterKeyBuilder.Build(requestIdentity, rule); if (rateLimitOptions.EnableEndpointRateLimiting && _config.EndpointCounterKeyBuilder != null) { key += _config.EndpointCounterKeyBuilder.Build(requestIdentity, rule); } var bytes = Encoding.UTF8.GetBytes(key); using var algorithm = new SHA1Managed(); var hash = algorithm.ComputeHash(bytes); return(Convert.ToBase64String(hash)); }
public abstract Task <RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions, CancellationToken cancellationToken = default);
protected RateLimitProcessor(RateLimitOptions options) { _options = options; }
public override async Task <RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions, CancellationToken cancellationToken = default) { var counter = new RateLimitCounter { Timestamp = DateTime.UtcNow, Count = 1 }; var counterId = BuildCounterKey(requestIdentity, rule, counterKeyBuilder, rateLimitOptions); // serial reads and writes on same key using (await AsyncLock.WriterLockAsync(counterId).ConfigureAwait(false)) { var entry = await _counterStore.GetAsync(counterId, cancellationToken); if (entry.HasValue) { // entry has not expired if (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); }