From 0ea27e7147c78b6930e3b9a24abb3ced71ef9620 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 8 Apr 2026 16:40:06 -0400 Subject: [PATCH] fix #6166 - move UseAntiforgery after UseNotFoundResponse and adjust 404 handling logic --- .../ApplicationBuilderExtensions.cs | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs index a18f4d02..a915f024 100644 --- a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs @@ -67,8 +67,8 @@ namespace Oqtane.Extensions app.UseOutputCache(); app.UseAuthentication(); app.UseAuthorization(); - app.UseAntiforgery(); app.UseNotFoundResponse(); + app.UseAntiforgery(); // execute any IServerStartup logic app.ConfigureOqtaneAssemblies(environment); @@ -153,28 +153,33 @@ namespace Oqtane.Extensions public static IApplicationBuilder UseNotFoundResponse(this IApplicationBuilder app) { + // set the route to be rendered on NavigationManager.NotFound() const string notFoundRoute = "/404"; app.UseStatusCodePagesWithReExecute(notFoundRoute, createScopeForStatusCodePages: true); + // middleware to determine if status code pages should be skipped app.Use(async (context, next) => { var path = context.Request.Path.Value ?? string.Empty; - if (string.IsNullOrEmpty(path) || ShouldSkipStatusCodeReExecution(path)) + if (ShouldSkipStatusCodeReExecution(path)) { - var feature = context.Features.Get(); - feature?.Enabled = false; + var statusCodePagesFeature = context.Features.Get(); + if (statusCodePagesFeature != null) + { + statusCodePagesFeature.Enabled = false; + } } await next(); }); + // middleware to rewrite the path for 404 status code responses on sites using subfolders app.Use(async (context, next) => { - var feature = context.Features.Get(); - var handled = false; - if (feature != null + var statusCodeReExecuteFeature = context.Features.Get(); + if (statusCodeReExecuteFeature != null && context.Response.StatusCode == (int)HttpStatusCode.NotFound - && notFoundRoute.Equals(context.Request.Path.Value, StringComparison.OrdinalIgnoreCase)) + && string.Equals(context.Request.Path.Value, notFoundRoute, StringComparison.OrdinalIgnoreCase)) { var alias = context.GetAlias(); if (!string.IsNullOrEmpty(alias?.Path)) @@ -183,20 +188,17 @@ namespace Oqtane.Extensions context.Request.Path = new PathString($"/{alias.Path}{notFoundRoute}"); try { - handled = true; await next(); } finally { context.Request.Path = originalPath; } + return; } } - if (!handled) - { - await next(); - } + await next(); }); return app; @@ -204,12 +206,16 @@ namespace Oqtane.Extensions static bool ShouldSkipStatusCodeReExecution(string path) { - return Constants.ReservedRoutes.Any(item => path.Contains("/" + item + "/")) || HasStaticFileExtension(path); + // skip requests for framework resources, reserved routes, and static files + return path.StartsWith("/_framework/", StringComparison.OrdinalIgnoreCase) || + path.StartsWith("/_content/", StringComparison.OrdinalIgnoreCase) || + Constants.ReservedRoutes.Any(item => path.Contains("/" + item + "/")) || + HasStaticFileExtension(path); } static bool HasStaticFileExtension(string path) { - return !string.IsNullOrEmpty(Path.GetExtension(path)); + return !string.IsNullOrEmpty(Path.GetExtension(path)) && Path.GetExtension(path).Length != 1; } } }