[backend/federation] Add short-lived cache for non-specific federation requests
This commit is contained in:
parent
762278426f
commit
ff59b07035
4 changed files with 27 additions and 0 deletions
|
@ -12,6 +12,7 @@ using Iceshrimp.Backend.Core.Middleware;
|
|||
using Iceshrimp.Backend.Core.Queues;
|
||||
using Iceshrimp.Backend.Core.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.OutputCaching;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
@ -108,6 +109,7 @@ public class ActivityPubController(
|
|||
|
||||
[HttpGet("/users/{id}")]
|
||||
[AuthorizedFetch]
|
||||
[OutputCache(PolicyName = "federation")]
|
||||
[MediaTypeRouteFilter("application/activity+json", "application/ld+json")]
|
||||
[OverrideResultType<ASActor>]
|
||||
[ProducesResults(HttpStatusCode.OK, HttpStatusCode.MovedPermanently)]
|
||||
|
@ -129,6 +131,7 @@ public class ActivityPubController(
|
|||
|
||||
[HttpGet("/users/{id}/collections/featured")]
|
||||
[AuthorizedFetch]
|
||||
[OutputCache(PolicyName = "federation")]
|
||||
[OverrideResultType<ASOrderedCollection>]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
[ProducesErrors(HttpStatusCode.NotFound)]
|
||||
|
@ -159,6 +162,7 @@ public class ActivityPubController(
|
|||
|
||||
[HttpGet("/@{acct}")]
|
||||
[AuthorizedFetch]
|
||||
[OutputCache(PolicyName = "federation")]
|
||||
[MediaTypeRouteFilter("application/activity+json", "application/ld+json")]
|
||||
[OverrideResultType<ASActor>]
|
||||
[ProducesResults(HttpStatusCode.OK, HttpStatusCode.MovedPermanently)]
|
||||
|
@ -212,6 +216,7 @@ public class ActivityPubController(
|
|||
|
||||
[HttpGet("/emoji/{name}")]
|
||||
[AuthorizedFetch]
|
||||
[OutputCache(PolicyName = "federation")]
|
||||
[MediaTypeRouteFilter("application/activity+json", "application/ld+json")]
|
||||
[OverrideResultType<ASEmoji>]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
|
|
|
@ -9,6 +9,7 @@ using Iceshrimp.Backend.Core.Federation.WebFinger;
|
|||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.OutputCaching;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
@ -17,6 +18,7 @@ namespace Iceshrimp.Backend.Controllers.Federation;
|
|||
[FederationApiController]
|
||||
[Route("/.well-known")]
|
||||
[EnableCors("well-known")]
|
||||
[OutputCache(PolicyName = "federation")]
|
||||
public class WellKnownController(IOptions<Config.InstanceSection> config, DatabaseContext db) : ControllerBase
|
||||
{
|
||||
[HttpGet("webfinger")]
|
||||
|
|
|
@ -374,10 +374,22 @@ public static class ServiceExtensions
|
|||
options.AddScheme<IAuthenticationHandler>("StubAuthenticationHandler", null);
|
||||
});
|
||||
}
|
||||
|
||||
public static void AddOutputCacheWithOptions(this IServiceCollection services)
|
||||
{
|
||||
services.AddOutputCache(options =>
|
||||
{
|
||||
options.AddPolicy("conditional", o => o.With(ctx => ctx.HttpContext.ShouldCacheOutput()));
|
||||
options.AddPolicy("federation", o => o.SetVaryByHeader("Accept").Expire(TimeSpan.FromSeconds(60)));
|
||||
options.DefaultExpirationTimeSpan = TimeSpan.FromDays(365);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class HttpContextExtensions
|
||||
{
|
||||
private const string CacheKey = "shouldCache";
|
||||
|
||||
public static string GetRateLimitPartition(this HttpContext ctx, bool includeRoute) =>
|
||||
(includeRoute ? ctx.Request.Path.ToString() + "#" : "") + (GetRateLimitPartitionInternal(ctx) ?? "");
|
||||
|
||||
|
@ -385,6 +397,11 @@ public static partial class HttpContextExtensions
|
|||
ctx.GetUser()?.Id ??
|
||||
ctx.Request.Headers["X-Forwarded-For"].FirstOrDefault() ??
|
||||
ctx.Connection.RemoteIpAddress?.ToString();
|
||||
|
||||
public static void CacheOutput(this HttpContext ctx) => ctx.Items[CacheKey] = true;
|
||||
|
||||
public static bool ShouldCacheOutput(this HttpContext ctx) =>
|
||||
ctx.Items.TryGetValue(CacheKey, out var s) && s is true;
|
||||
}
|
||||
|
||||
#region AsyncDataProtection handlers
|
||||
|
|
|
@ -24,6 +24,7 @@ builder.Services
|
|||
.AddPlugins(PluginLoader.Assemblies);
|
||||
|
||||
builder.Services.AddSwaggerGenWithOptions();
|
||||
builder.Services.AddOutputCacheWithOptions();
|
||||
builder.Services.AddLogging(logging => logging.AddCustomConsoleFormatter());
|
||||
builder.Services.AddDatabaseContext(builder.Configuration);
|
||||
builder.Services.AddSlidingWindowRateLimiter();
|
||||
|
@ -38,6 +39,7 @@ builder.Services.AddAntiforgery(o => o.Cookie.Name = "CSRF-Token");
|
|||
|
||||
builder.Services.AddServices(builder.Configuration);
|
||||
builder.Services.ConfigureServices(builder.Configuration);
|
||||
|
||||
builder.WebHost.ConfigureKestrel(builder.Configuration);
|
||||
builder.WebHost.UseStaticWebAssets();
|
||||
|
||||
|
@ -64,6 +66,7 @@ app.UseAuthorization();
|
|||
app.UseWebSockets(new WebSocketOptions { KeepAliveInterval = TimeSpan.FromSeconds(30) });
|
||||
app.UseCustomMiddleware();
|
||||
app.UseAntiforgery();
|
||||
app.UseOutputCache();
|
||||
|
||||
app.MapStaticAssetsWithTransparentDecompression();
|
||||
app.MapControllers();
|
||||
|
|
Loading…
Add table
Reference in a new issue