public async Task Invoke(HttpContext httpContext) { // check if rate limiting is enabled if (_options == null) { await _next.Invoke(httpContext); return; } // compute identity from request var identity = SetIdentity(httpContext); // check white list if (_processor.IsWhitelisted(identity)) { await _next.Invoke(httpContext); return; } var rules = _processor.GetMatchingRules(identity); foreach (var rule in rules) { if (rule.Limit > 0) { // increment counter var counter = _processor.ProcessRequest(identity, rule); // check if key expired if (counter.Timestamp + rule.PeriodTimespan.Value < DateTime.UtcNow) { continue; } // check if limit is reached if (counter.TotalRequests > rule.Limit) { //compute retry after value var retryAfter = _processor.RetryAfterFrom(counter.Timestamp, rule); // log blocked request LogBlockedRequest(httpContext, identity, counter, rule); // break execution await ReturnQuotaExceededResponse(httpContext, rule, retryAfter); return; } } // if limit is zero or less, block the request. else { // process request count var counter = _processor.ProcessRequest(identity, rule); // log blocked request LogBlockedRequest(httpContext, identity, counter, rule); // break execution (Int32 max used to represent infinity) await ReturnQuotaExceededResponse(httpContext, rule, Int32.MaxValue.ToString(System.Globalization.CultureInfo.InvariantCulture)); return; } } //set X-Rate-Limit headers for the longest period if (rules.Any() && !_options.DisableRateLimitHeaders) { var rule = rules.OrderByDescending(x => x.PeriodTimespan.Value).First(); var headers = _processor.GetRateLimitHeaders(identity, rule); headers.Context = httpContext; httpContext.Response.OnStarting(SetRateLimitHeaders, state: headers); } await _next.Invoke(httpContext); }
public async Task Invoke(HttpContext httpContext) { // check if rate limiting is enabled if (_options == null) { await _next.Invoke(httpContext); return; } // compute identity from request var identity = SetIdentity(httpContext); _logger.LogInformation($"Identity; User:[{identity.ClientId}]; IP:[{identity.ClientIp}]"); // check white list if (_processor.IsWhitelisted(identity)) { await _next.Invoke(httpContext); return; } var rules = _processor.GetMatchingRules(identity); foreach (var rule in rules) { if (rule.Limit > 0) { // increment counter var counter = _processor.ProcessRequest(identity, rule); // check if key expired if (counter.Timestamp + rule.PeriodTimespan.Value < DateTime.UtcNow) { continue; } // check if limit is reached if (counter.TotalRequests > rule.Limit) { //compute retry after value var retryAfter = _processor.RetryAfterFrom(counter.Timestamp, rule); // log blocked request LogBlockedRequest(httpContext, identity, counter, rule); // break execution await ReturnQuotaExceededResponse(httpContext, rule, retryAfter); return; } } } //set X-Rate-Limit headers for the longest period if (rules.Any() && !_options.DisableRateLimitHeaders) { var rule = rules.OrderByDescending(x => x.PeriodTimespan.Value).First(); var headers = _processor.GetRateLimitHeaders(identity, rule); headers.Context = httpContext; httpContext.Response.OnStarting(SetRateLimitHeaders, state: headers); } await _next.Invoke(httpContext); }