/
idalynnn
/
api
Обзор
Документация
Войти
/
idalynnn
/
api
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Middleware/SimpleRateLimitMiddleware.cs
65 строк
2 KB
idalynnn
init
13 дек 2025, 05:34
13 дек 2025, 05:34
44c310a
Код
Авторство
О чём код?
using System.Collections.Concurrent; namespace TaskTrackerApi.Middleware; public class SimpleRateLimitMiddleware { private readonly RequestDelegate _next; private static readonly ConcurrentDictionary<string, Counter> Store = new(); private readonly int _limit; private readonly TimeSpan _window; public SimpleRateLimitMiddleware(RequestDelegate next, IConfiguration config) { _next = next; _limit = config.GetValue<int>("RateLimit:Limit", 20); _window = TimeSpan.FromSeconds(config.GetValue<int>("RateLimit:WindowSeconds", 60)); } public async Task Invoke(HttpContext context) { var ip = context.Connection.RemoteIpAddress?.ToString() ?? "unknown"; var now = DateTime.UtcNow; var counter = Store.AddOrUpdate( ip, _ => new Counter { WindowStart = now, Count = 0 }, (_, existing) => { if (now - existing.WindowStart >= _window) { existing.WindowStart = now; existing.Count = 0; } return existing; }); if (counter.Count >= _limit) { var retryAfter = (int)Math.Ceiling((_window - (now - counter.WindowStart)).TotalSeconds); if (retryAfter < 0) retryAfter = 0; context.Response.StatusCode = StatusCodes.Status429TooManyRequests; context.Response.Headers["Retry-After"] = retryAfter.ToString(); context.Response.Headers["X-Limit-Remaining"] = "0"; await context.Response.WriteAsJsonAsync(new { message = "Too many requests", retry_after_seconds = retryAfter }); return; } counter.Count++; context.Response.Headers["X-Limit-Remaining"] = (_limit - counter.Count).ToString(); await _next(context); } private class Counter { public DateTime WindowStart { get; set; } public int Count { get; set; } } }