Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not redirect to 404 with 302 #6967

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
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.Routing;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
Expand Down Expand Up @@ -167,9 +169,11 @@ await logger.ErrorAsync($"Error 404. The requested page ({originalPath}) was not
try
{
//get new path
var pageNotFoundPath = "/page-not-found";
var lang = GetLanguagePart(context);
var pageNotFoundPath = $"{lang}/page-not-found";

//re-execute request with new path
context.HttpContext.Response.Redirect(context.HttpContext.Request.PathBase + pageNotFoundPath);
await CreateHandler(pageNotFoundPath, null)(context);
}
finally
{
Expand Down Expand Up @@ -545,4 +549,73 @@ public static void UseNopWebMarkupMin(this IApplicationBuilder application)

application.UseWebMarkupMin();
}

/// <summary>
/// Retrieves a language url part based on the given StatusCodeContext.
/// </summary>
/// <param name="context">The StatusCodeContext used to determine the language part.</param>
/// <returns>The language url part as a string.</returns>
private static string GetLanguagePart(StatusCodeContext context)
{
if (!DataSettingsManager.IsDatabaseInstalled()) return string.Empty;
var localizationSettings = EngineContext.Current.Resolve<LocalizationSettings>();
if (!localizationSettings.SeoFriendlyUrlsForLanguagesEnabled) return string.Empty;
return context.HttpContext.GetRouteValue(NopRoutingDefaults.RouteValue.Language) is string lang ? $"/{lang}" : "/en";
}

/// <summary>
/// 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.
/// </summary>
/// <param name="pathFormat">A string representing the path format.</param>
/// <param name="queryFormat">A string representing the query format.</param>
/// <param name="next">The next request delegate in the pipeline.</param>
/// <returns>A function that handles the status code context.</returns>
private static Func<StatusCodeContext, Task> 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<IRouteValuesFeature>();
context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(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<IStatusCodeReExecuteFeature>(null);
}
});
}
}