Добавил RateLimiter
All checks were successful
Create and publish a Docker image / Publish image (push) Successful in 11m22s

This commit is contained in:
2025-09-06 22:07:37 +03:00
parent 5f52e16dbd
commit ea254c1c02
2 changed files with 39 additions and 6 deletions

View File

@@ -1,10 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using SfeduSchedule.Services;
namespace SfeduSchedule.Controllers
{
[ApiController]
[Route("api/[controller]")]
[EnableRateLimiting("throttle")]
public class ScheduleController(ModeusService modeusService) : ControllerBase
{
/// <summary>
@@ -13,6 +15,7 @@ namespace SfeduSchedule.Controllers
/// <param name="attendeePersonId">Список GUID пользователей, для которых запрашивается расписание.</param>
/// <returns>Список событий расписания.</returns>
/// <response code="200">Возвращает расписание</response>
/// <response code="429">Слишком много запросов</response>
[HttpGet]
[Route("test")]
public async Task<IActionResult> Get([FromQuery] List<Guid> attendeePersonId, [FromQuery] DateTime? startDate, [FromQuery] DateTime? endDate)
@@ -31,6 +34,7 @@ namespace SfeduSchedule.Controllers
/// <param name="request">Объект запроса, содержащий параметры фильтрации расписания.</param>
/// <returns>Список событий расписания.</returns>
/// <response code="200">Возвращает расписание</response>
/// <response code="429">Слишком много запросов</response>
[HttpPost]
public async Task<IActionResult> Post([FromBody] ModeusScheduleRequest request)
{

View File

@@ -1,3 +1,4 @@
using System.Threading.RateLimiting;
using Microsoft.Identity.Web;
using Quartz;
using SfeduSchedule;
@@ -13,13 +14,13 @@ string? tgChatId = configuration["TG_CHAT_ID"];
string? tgToken = configuration["TG_TOKEN"];
string updateJwtCron = configuration["UPDATE_JWT_CRON"] ?? "0 4 * ? * *";
// создать папку data если не существует
var dataDirectory = Path.Combine(AppContext.BaseDirectory, "data");
if (!Directory.Exists(dataDirectory))
{
Directory.CreateDirectory(dataDirectory);
}
GlobalVariables.JwtFilePath = Path.Combine(dataDirectory, "jwt.txt");
@@ -35,7 +36,8 @@ if (!string.IsNullOrEmpty(tgChatId) && !string.IsNullOrEmpty(tgToken))
options.LogLevel = new Dictionary<string, LogLevel>
{
{ "Default", LogLevel.Error },
{ "SfeduSchedule.Jobs.UpdateJwtJob", LogLevel.Information }
{ "SfeduSchedule.Jobs.UpdateJwtJob", LogLevel.Information },
{ "Program", LogLevel.Information }
};
});
@@ -70,12 +72,37 @@ builder.Services.AddSwaggerGen(options =>
options.IncludeXmlComments(xmlPath);
});
builder.Services.AddRateLimiter(options =>
{
options.AddPolicy("throttle", httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: httpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown",
factory: _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 20,
Window = TimeSpan.FromSeconds(10)
}));
options.OnRejected = async (context, cancellationToken) =>
{
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
context.HttpContext.Response.Headers["Retry-After"] = "60";
await context.HttpContext.Response.WriteAsync("Rate limit exceeded. Please try again later.",
cancellationToken);
var reqLogger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
reqLogger.LogWarning("Rate limit exceeded for IP: {IpAddress}",
context.HttpContext.Connection.RemoteIpAddress);
};
});
var app = builder.Build();
app.UseForwardedHeaders();
var logger = app.Services.GetRequiredService<ILogger<Program>>();
app.UseForwardedHeaders();
if (string.IsNullOrEmpty(preinstalledJwtToken))
{
var schedulerFactory = app.Services.GetRequiredService<ISchedulerFactory>();
@@ -103,7 +130,8 @@ if (string.IsNullOrEmpty(preinstalledJwtToken))
}
else
{
logger.LogInformation("Файл jwt.txt не содержит дату истечения или она некорректна, выполняем обновление токена");
logger.LogInformation(
"Файл jwt.txt не содержит дату истечения или она некорректна, выполняем обновление токена");
await scheduler.TriggerJob(jobKey);
}
}
@@ -131,5 +159,6 @@ app.MapGet("/", async context =>
app.MapControllers();
app.Run();
app.UseRateLimiter();
app.Run();