public async Task Invoke(DownstreamContext context) { var options = context.DownstreamReRoute.RateLimitOptions; // check if rate limiting is enabled if (!context.DownstreamReRoute.EnableEndpointEndpointRateLimiting) { Logger.LogInformation($"EndpointRateLimiting is not enabled for {context.DownstreamReRoute.DownstreamPathTemplate.Value}"); await _next.Invoke(context); return; } // compute identity from request var identity = SetIdentity(context.HttpContext, options); // check white list if (IsWhitelisted(identity, options)) { Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} is white listed from rate limiting"); await _next.Invoke(context); return; } var rule = options.RateLimitRule; if (rule.Limit > 0) { // increment counter var counter = _processor.ProcessRequest(identity, options); // 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(context.HttpContext, identity, counter, rule, context.DownstreamReRoute); var retrystring = retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture); // break execution await ReturnQuotaExceededResponse(context.HttpContext, options, retrystring); return; } } //set X-Rate-Limit headers for the longest period if (!options.DisableRateLimitHeaders) { var headers = _processor.GetRateLimitHeaders(context.HttpContext, identity, options); context.HttpContext.Response.OnStarting(SetRateLimitHeaders, state: headers); } await _next.Invoke(context); }
public async Task Invoke(HttpContext context) { _logger.LogDebug("started calling RateLimit middleware"); var options = DownstreamRoute.ReRoute.RateLimitOptions; // check if rate limiting is enabled if (!DownstreamRoute.ReRoute.EnableEndpointRateLimiting) { await _next.Invoke(context); return; } // compute identity from request var identity = SetIdentity(context, options); // check white list if (IsWhitelisted(identity, options)) { await _next.Invoke(context); return; } var rule = options.RateLimitRule; if (rule.Limit > 0) { // increment counter var counter = _processor.ProcessRequest(identity, options); // 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(context, identity, counter, rule); // break execution await ReturnQuotaExceededResponse(context, options, retryAfter); return; } } //set X-Rate-Limit headers for the longest period if (!options.DisableRateLimitHeaders) { var headers = _processor.GetRateLimitHeaders(context, identity, options); context.Response.OnStarting(SetRateLimitHeaders, state: headers); } await _next.Invoke(context); }
public static void RequestProcessing(HttpContext httpContext) { if (!Configurationed) { return; } // check if rate limiting is enabled if (Options == null) { return; } // compute identity from request var identity = SetIdentity(httpContext); // check white list if (Processor.IsWhitelisted(identity)) { 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 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; headers.Context.Response.Headers["X-Rate-Limit-Limit"] = headers.Limit; headers.Context.Response.Headers["X-Rate-Limit-Remaining"] = headers.Remaining; headers.Context.Response.Headers["X-Rate-Limit-Reset"] = headers.Reset; } }