From 923a3fb90e20fc63d7a1416ceef317d92399d1dc Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Fri, 26 Jun 2026 03:41:09 +0330 Subject: [PATCH] Stop the CDN serving a stale homepage (archived listings showing as live cards) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The homepage query already filters Status==Open, but the wcdn CDN was caching the rendered HTML. A listing archived by the post-crawl cleanup AFTER caching still appeared as a card on the stale copy — clicking it hit the correct 410. Force HTML revalidation (no-cache) so listing pages are always fresh; mark logged-in pages private/no-store and Vary on Cookie so the CDN never mixes anonymous and authenticated copies. Static assets keep their long cache headers. Co-Authored-By: Claude Opus 4.8 --- src/JobsMedical.Web/Program.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/JobsMedical.Web/Program.cs b/src/JobsMedical.Web/Program.cs index 76df6da..df2e616 100644 --- a/src/JobsMedical.Web/Program.cs +++ b/src/JobsMedical.Web/Program.cs @@ -147,6 +147,28 @@ app.UseMiddleware(); app.UseAuthentication(); app.UseAuthorization(); +// HTML pages list live, fast-changing data (listings get archived between crawls). The CDN must NOT +// serve a stale homepage/detail copy — that's how an archived (410) listing can still appear as a +// card. Force revalidation on HTML; never let a private (logged-in) page be cached by the CDN, and +// Vary on the auth cookie so an anonymous copy is never handed to a logged-in visitor (or vice-versa). +// Static assets (css/js/fonts/images) are untouched — they keep MapStaticAssets' long cache headers. +app.Use(async (ctx, next) => +{ + ctx.Response.OnStarting(() => + { + if (ctx.Response.ContentType is string ct && ct.StartsWith("text/html") + && !ctx.Response.Headers.ContainsKey("Cache-Control")) + { + ctx.Response.Headers.CacheControl = ctx.User.Identity?.IsAuthenticated == true + ? "private, no-store" + : "no-cache, must-revalidate"; + ctx.Response.Headers.Vary = "Cookie"; + } + return Task.CompletedTask; + }); + await next(); +}); + app.MapStaticAssets(); app.MapRazorPages() .WithStaticAssets();