на основе этой статьи: https://www.softfluent.com/blog/dev/Page-redirection-and-URL-Rewriting-with-ASP-NET-Core
При разработке веб-приложения часто требуется добавить некоторые правила перенаправления.Наиболее распространенные правила перенаправления: перенаправление с «http» на «https», добавление «www» или перемещение веб-сайта в другой домен.Перезапись URL часто используется для предоставления удобного для пользователя URL.
Я хочу объяснить разницу между перенаправлением и перезаписью.При перенаправлении клиент отправляет HTTP 301 или 302, сообщая клиенту, что он должен получить доступ к странице, используя другой URL-адрес.Браузер обновит URL, видимый в адресной строке, и сделает новый запрос, используя новый URL.С другой стороны, перезапись происходит на сервере и представляет собой перевод одного URL-адреса на другой.Сервер будет использовать новый URL для обработки запроса.Клиент не знает, что сервер переписал URL.
В IIS вы можете использовать файл web.config
для определения правил перенаправления и перезаписи или использовать RewritePath
:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to https">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="Off" />
<add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
<add input="{HTTP_HOST}" negate="true" pattern="localhost" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Однако это больше не работает с ASP.NET Core.Вместо этого вы можете использовать новый пакет NuGet: Microsoft.AspNetCore.Rewrite (GitHub).Этот пакет очень прост в использовании.Откройте файл startup.cs и отредактируйте метод Configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ISiteProvider siteProvider)
{
app.UseRewriter(new RewriteOptions()
.AddRedirectToHttps()
.AddRedirect(@"^section1/(.*)", "new/$1", (int)HttpStatusCode.Redirect)
.AddRedirect(@"^section2/(\\d+)/(.*)", "new/$1/$2", (int)HttpStatusCode.MovedPermanently)
.AddRewrite("^feed$", "/?format=rss", skipRemainingRules: false));
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Правила основаны на регулярных выражениях и подстановках.Регулярное выражение оценивается по HttpContext.Request.Path, который не включает ни домен, ни протокол.Это означает, что вы не можете перенаправить на другой домен или добавить «www», используя этот метод, но не волнуйтесь, я покажу вам, как это сделать после!
Microsoft решила помочь вам с этимновый пакетДействительно, если у вас уже есть файл web.config или даже файл .htaccess (ядро .net является кроссплатформенным), вы можете импортировать их напрямую:
app.UseRewriter(new RewriteOptions()
.AddIISUrlRewrite(env.ContentRootFileProvider, "web.config")
.AddApacheModRewrite(env.ContentRootFileProvider, ".htaccess"));
Если у вас есть сложные правила, которые не могут бытьВыражаясь с помощью регулярных выражений, вы можете написать свое собственное правило.Правило - это класс, который реализует Microsoft.AspNetCore.Rewrite.IRule:
// app.UseRewriter(new RewriteOptions().Add(new RedirectWwwRule()));
public class RedirectWwwRule : Microsoft.AspNetCore.Rewrite.IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public bool ExcludeLocalhost { get; set; } = true;
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var host = request.Host;
if (host.Host.StartsWith("www", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
if (ExcludeLocalhost && string.Equals(host.Host, "localhost", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
string newPath = request.Scheme + "://www." + host.Value + request.PathBase + request.Path + request.QueryString;
var response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = newPath;
context.Result = RuleResult.EndResponse; // Do not continue processing the request
}
}