From 80b094531e9a11c960c6b8e4199b8222303ef888 Mon Sep 17 00:00:00 2001 From: Jan Nielsen Date: Mon, 18 Dec 2023 22:35:18 +0100 Subject: [PATCH] Do not redirect to 404 with 302 --- .../ApplicationBuilderExtensions.cs | 88 ++++++++++++++----- 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ApplicationBuilderExtensions.cs b/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ApplicationBuilderExtensions.cs index 2eaff750e51..2743a6e9688 100644 --- a/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ApplicationBuilderExtensions.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.StaticFiles; @@ -169,7 +170,7 @@ await logger.ErrorAsync($"Error 404. The requested page ({originalPath}) was not //get new path var pageNotFoundPath = "/page-not-found"; //re-execute request with new path - context.HttpContext.Response.Redirect(context.HttpContext.Request.PathBase + pageNotFoundPath); + await CreateHandler(pageNotFoundPath, null)(context); } finally { @@ -231,16 +232,8 @@ public static void UseNopWebOptimizer(this IApplicationBuilder application) application.UseWebOptimizer(webHostEnvironment, [ - new FileProviderOptions - { - RequestPath = new PathString("/Plugins"), - FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Plugins")) - }, - new FileProviderOptions - { - RequestPath = new PathString("/Themes"), - FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Themes")) - } + new FileProviderOptions { RequestPath = new PathString("/Plugins"), FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Plugins")) }, + new FileProviderOptions { RequestPath = new PathString("/Themes"), FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Themes")) } ]); } @@ -282,17 +275,13 @@ void staticFileResponse(StaticFileResponseContext context) //themes static files application.UseStaticFiles(new StaticFileOptions { - FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Themes")), - RequestPath = new PathString("/Themes"), - OnPrepareResponse = staticFileResponse + FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Themes")), RequestPath = new PathString("/Themes"), OnPrepareResponse = staticFileResponse }); //plugins static files var staticFileOptions = new StaticFileOptions { - FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Plugins")), - RequestPath = new PathString("/Plugins"), - OnPrepareResponse = staticFileResponse + FileProvider = new PhysicalFileProvider(fileProvider.MapPath(@"Plugins")), RequestPath = new PathString("/Plugins"), OnPrepareResponse = staticFileResponse }; //exclude files in blacklist @@ -315,10 +304,7 @@ void staticFileResponse(StaticFileResponseContext context) application.UseStaticFiles(staticFileOptions); //add support for backups - var provider = new FileExtensionContentTypeProvider - { - Mappings = { [".bak"] = MimeTypes.ApplicationOctetStream } - }; + var provider = new FileExtensionContentTypeProvider { Mappings = { [".bak"] = MimeTypes.ApplicationOctetStream } }; application.UseStaticFiles(new StaticFileOptions { @@ -342,9 +328,7 @@ void staticFileResponse(StaticFileResponseContext context) application.UseStaticFiles(new StaticFileOptions { - FileProvider = new PhysicalFileProvider(fileProvider.GetAbsolutePath("icons")), - RequestPath = "/icons", - ContentTypeProvider = provider + FileProvider = new PhysicalFileProvider(fileProvider.GetAbsolutePath("icons")), RequestPath = "/icons", ContentTypeProvider = provider }); if (DataSettingsManager.IsDatabaseInstalled()) @@ -545,4 +529,60 @@ public static void UseNopWebMarkupMin(this IApplicationBuilder application) application.UseWebMarkupMin(); } + + /// + /// Creates a request handling method based on specified paths and a next request delegate. + /// It was inspired by UseStatusCodePagesWithReExecute method from Microsoft.AspNetCore.Builder.StatusCodePagesExtensions class. + /// + /// A string representing the path format. + /// A string representing the query format. + /// The next request delegate in the pipeline. + /// A function that handles the status code context. + private static Func CreateHandler(string pathFormat, string queryFormat, RequestDelegate next = null) + { + return (async context => + { + var statusCode = context.HttpContext.Response.StatusCode; + var pathString = new PathString(string.Format(CultureInfo.InvariantCulture, pathFormat, statusCode)); + var str = queryFormat == null ? null : string.Format(CultureInfo.InvariantCulture, queryFormat, statusCode); + var queryString = queryFormat == null ? QueryString.Empty : new QueryString(str); + var originalPath = context.HttpContext.Request.Path; + var originalQueryString = context.HttpContext.Request.QueryString; + var routeValuesFeature = context.HttpContext.Features.Get(); + context.HttpContext.Features.Set(new StatusCodeReExecuteFeature + { + OriginalPathBase = context.HttpContext.Request.PathBase.Value!, + OriginalPath = originalPath.Value!, + OriginalQueryString = (originalQueryString.HasValue ? originalQueryString.Value : null), + Endpoint = context.HttpContext.GetEndpoint(), + RouteValues = routeValuesFeature?.RouteValues + }); + context.HttpContext.SetEndpoint(null); + if (routeValuesFeature != null) + routeValuesFeature.RouteValues = null!; + context.HttpContext.Request.Path = pathString; + context.HttpContext.Request.QueryString = queryString; + try + { + if (next != null) + { + await next(context.HttpContext); + originalPath = new PathString(); + originalQueryString = new QueryString(); + } + else + { + await context.Next(context.HttpContext); + originalPath = new PathString(); + originalQueryString = new QueryString(); + } + } + finally + { + context.HttpContext.Request.QueryString = originalQueryString; + context.HttpContext.Request.Path = originalPath; + context.HttpContext.Features.Set(null); + } + }); + } } \ No newline at end of file