using Microsoft.AspNetCore.OutputCaching; using Microsoft.Extensions.Primitives; using Tiku.Application.Security; namespace Tiku.Api.Caching; internal sealed class TenantPublicOutputCachePolicy : IOutputCachePolicy { public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken) { var request = context.HttpContext.Request; var tenantId = context.HttpContext.RequestServices.GetRequiredService().TenantId; var enabled = HttpMethods.IsGet(request.Method) && tenantId.HasValue && StringValues.IsNullOrEmpty(request.Headers.Authorization) && context.HttpContext.User.Identity?.IsAuthenticated != true; context.EnableOutputCaching = enabled; context.AllowCacheLookup = enabled; context.AllowCacheStorage = enabled; context.AllowLocking = true; if (enabled) { var resolvedTenantId = tenantId.GetValueOrDefault(); context.CacheVaryByRules.QueryKeys = "*"; context.CacheVaryByRules.HeaderNames = new StringValues("Accept-Encoding"); context.CacheVaryByRules.VaryByValues["tenant"] = resolvedTenantId.ToString("N"); context.Tags.Add($"tenant:{resolvedTenantId:N}"); } return ValueTask.CompletedTask; } public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken) => ValueTask.CompletedTask; public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken) { var response = context.HttpContext.Response; if (response.StatusCode != StatusCodes.Status200OK || !StringValues.IsNullOrEmpty(response.Headers.SetCookie) || context.HttpContext.User.Identity?.IsAuthenticated == true) { context.AllowCacheStorage = false; } return ValueTask.CompletedTask; } }