feat: add cache control in response
This commit is contained in:
parent
80dc2e412c
commit
565252382c
26
Endpoint/Common/Attributes/CacheMaxAgeAttribute.cs
Normal file
26
Endpoint/Common/Attributes/CacheMaxAgeAttribute.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Mirea.Api.Endpoint.Common.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||||
|
public class CacheMaxAgeAttribute : Attribute
|
||||||
|
{
|
||||||
|
public int MaxAge { get; }
|
||||||
|
|
||||||
|
public CacheMaxAgeAttribute(int days = 0, int hours = 0, int minutes = 0)
|
||||||
|
{
|
||||||
|
MaxAge = (int)new TimeSpan(days, hours, minutes, 0).TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheMaxAgeAttribute(int minutes) : this(0, 0, minutes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheMaxAgeAttribute(bool usingSetting = false)
|
||||||
|
{
|
||||||
|
if (usingSetting)
|
||||||
|
MaxAge = -1;
|
||||||
|
else
|
||||||
|
MaxAge = 0;
|
||||||
|
}
|
||||||
|
}
|
@ -17,11 +17,14 @@ using System.Threading.Tasks;
|
|||||||
namespace Mirea.Api.Endpoint.Controllers.V1;
|
namespace Mirea.Api.Endpoint.Controllers.V1;
|
||||||
|
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0")]
|
||||||
|
[CacheMaxAge(true)]
|
||||||
public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConfig> config) : BaseController
|
public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConfig> config) : BaseController
|
||||||
{
|
{
|
||||||
|
[CacheMaxAge(1, 0)]
|
||||||
[HttpGet("StartTerm")]
|
[HttpGet("StartTerm")]
|
||||||
public ActionResult<DateOnly> GetStartTerm() => config.Value.ScheduleSettings!.StartTerm;
|
public ActionResult<DateOnly> GetStartTerm() => config.Value.ScheduleSettings!.StartTerm;
|
||||||
|
|
||||||
|
[CacheMaxAge(1, 0)]
|
||||||
[HttpGet("PairPeriod")]
|
[HttpGet("PairPeriod")]
|
||||||
public ActionResult<Dictionary<int, PairPeriodTime>> GetPairPeriod() => config.Value.ScheduleSettings!.PairPeriod.ConvertToDto();
|
public ActionResult<Dictionary<int, PairPeriodTime>> GetPairPeriod() => config.Value.ScheduleSettings!.PairPeriod.ConvertToDto();
|
||||||
|
|
||||||
@ -105,7 +108,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
|||||||
[FromQuery] int[]? professors = null,
|
[FromQuery] int[]? professors = null,
|
||||||
[FromQuery] int[]? lectureHalls = null) =>
|
[FromQuery] int[]? lectureHalls = null) =>
|
||||||
await Get(new ScheduleRequest
|
await Get(new ScheduleRequest
|
||||||
{
|
{
|
||||||
Disciplines = disciplines,
|
Disciplines = disciplines,
|
||||||
IsEven = isEven,
|
IsEven = isEven,
|
||||||
Groups = [id],
|
Groups = [id],
|
||||||
@ -133,7 +136,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
|||||||
[FromQuery] int[]? groups = null,
|
[FromQuery] int[]? groups = null,
|
||||||
[FromQuery] int[]? lectureHalls = null) =>
|
[FromQuery] int[]? lectureHalls = null) =>
|
||||||
await Get(new ScheduleRequest
|
await Get(new ScheduleRequest
|
||||||
{
|
{
|
||||||
Disciplines = disciplines,
|
Disciplines = disciplines,
|
||||||
IsEven = isEven,
|
IsEven = isEven,
|
||||||
Groups = groups,
|
Groups = groups,
|
||||||
@ -161,7 +164,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
|||||||
[FromQuery] int[]? groups = null,
|
[FromQuery] int[]? groups = null,
|
||||||
[FromQuery] int[]? professors = null) =>
|
[FromQuery] int[]? professors = null) =>
|
||||||
await Get(new ScheduleRequest
|
await Get(new ScheduleRequest
|
||||||
{
|
{
|
||||||
Disciplines = disciplines,
|
Disciplines = disciplines,
|
||||||
IsEven = isEven,
|
IsEven = isEven,
|
||||||
Groups = groups,
|
Groups = groups,
|
||||||
@ -189,11 +192,11 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
|||||||
[FromQuery] int[]? professors = null,
|
[FromQuery] int[]? professors = null,
|
||||||
[FromQuery] int[]? lectureHalls = null) =>
|
[FromQuery] int[]? lectureHalls = null) =>
|
||||||
await Get(new ScheduleRequest
|
await Get(new ScheduleRequest
|
||||||
{
|
{
|
||||||
Disciplines = [id],
|
Disciplines = [id],
|
||||||
IsEven = isEven,
|
IsEven = isEven,
|
||||||
Groups = groups,
|
Groups = groups,
|
||||||
Professors = professors,
|
Professors = professors,
|
||||||
LectureHalls = lectureHalls
|
LectureHalls = lectureHalls
|
||||||
});
|
});
|
||||||
}
|
}
|
81
Endpoint/Middleware/CacheMaxAgeMiddleware.cs
Normal file
81
Endpoint/Middleware/CacheMaxAgeMiddleware.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
using Cronos;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Mirea.Api.Endpoint.Common.Attributes;
|
||||||
|
using Mirea.Api.Endpoint.Common.Settings;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mirea.Api.Endpoint.Middleware;
|
||||||
|
|
||||||
|
public class CacheMaxAgeMiddleware(RequestDelegate next, IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
public async Task InvokeAsync(HttpContext context)
|
||||||
|
{
|
||||||
|
if (!context.Response.StatusCode.ToString().StartsWith('2'))
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var endpoint = context.GetEndpoint();
|
||||||
|
|
||||||
|
var actionDescriptor = endpoint?.Metadata.GetMetadata<Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor>();
|
||||||
|
|
||||||
|
if (actionDescriptor == null)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var controllerType = actionDescriptor.ControllerTypeInfo;
|
||||||
|
var methodInfo = actionDescriptor.MethodInfo;
|
||||||
|
|
||||||
|
var maxAgeAttribute = methodInfo.GetCustomAttribute<CacheMaxAgeAttribute>() ?? controllerType.GetCustomAttribute<CacheMaxAgeAttribute>();
|
||||||
|
|
||||||
|
if (maxAgeAttribute == null)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (maxAgeAttribute.MaxAge)
|
||||||
|
{
|
||||||
|
case < 0:
|
||||||
|
{
|
||||||
|
DateTime? nextDate;
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
|
using (var scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var updateCronString = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<GeneralConfig>>().Value.ScheduleSettings?.CronUpdateSchedule;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(updateCronString) ||
|
||||||
|
!CronExpression.TryParse(updateCronString, CronFormat.Standard, out var updateCron))
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextDate = updateCron.GetNextOccurrence(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nextDate.HasValue)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.Headers.CacheControl = "max-age=" + (int)(nextDate.Value - now).TotalSeconds;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case > 0:
|
||||||
|
context.Response.Headers.CacheControl = "max-age=" + maxAgeAttribute.MaxAge;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await next(context);
|
||||||
|
}
|
||||||
|
}
|
@ -125,9 +125,10 @@ public class Program
|
|||||||
|
|
||||||
app.UseCustomSwagger(app.Services);
|
app.UseCustomSwagger(app.Services);
|
||||||
|
|
||||||
app.UseMiddleware<MaintenanceModeMiddleware>();
|
|
||||||
app.UseMiddleware<CustomExceptionHandlerMiddleware>();
|
app.UseMiddleware<CustomExceptionHandlerMiddleware>();
|
||||||
|
app.UseMiddleware<MaintenanceModeMiddleware>();
|
||||||
app.UseMiddleware<JwtRevocationMiddleware>();
|
app.UseMiddleware<JwtRevocationMiddleware>();
|
||||||
|
app.UseMiddleware<CacheMaxAgeMiddleware>();
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user