Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Note
Это не последняя версия этой статьи. В текущей версии см. версию .NET 10 этой статьи.
Warning
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущей версии см. версию .NET 10 этой статьи.
Авторы: Кирк Ларкин (Kirk Larkin) и Рик Андерсон (Rick Anderson)
Эта статья содержит вводные сведения о переопределении URL-адресов и инструкции по использованию ПО промежуточного слоя для переопределения URL-адресов в приложениях ASP.NET Core.
Переопределение URL-адресов представляет собой изменение URL-адресов запросов на основе одного или нескольких предопределенных правил. Переопределение URL-адресов создает абстракцию между расположениями ресурсов и их адресами, позволяя убрать тесную связь между ними. Существует несколько сценариев, где может пригодиться переопределение URL-адресов:
- Временное или постоянное перемещение или замещение ресурсов сервера с сохранением стабильных указателей для этих ресурсов.
- Разделение обработки запросов между разными приложениями или разными областями одного приложения.
- Удаление, добавление или переупорядочение сегментов URL-адресов для входящих запросов.
- Оптимизация общедоступных URL-адресов в целях оптимизации для поисковых систем (SEO).
- Разрешение использования понятных общедоступных URL-адресов, чтобы помочь посетителям прогнозировать содержимое, возвращаемое в результате запроса ресурса.
- Перенаправление небезопасных запросов на защищенные конечные точки.
- Запрет вставки прямых ссылок, когда внешний сайт использует статический ресурс, размещенный на другом сайте, привязывая ресурс к своему содержимому.
Переопределение URL-адресов может снижать производительность приложения. Ограничьте количество и сложность правил.
Перенаправление и переопределение URL-адресов
Разница между перенаправлением и переопределением URL-адресов может показаться незначительной, но она оказывает существенное влияние на предоставление ресурсов клиентам. ПО промежуточного слоя для переопределения URL-адресов в ASP.NET Core удовлетворяет потребность в обеих этих функциях.
Перенаправление URL-адресов является операцией на стороне клиента, которая предписывает клиенту обратиться к ресурсу по другому адресу, отличному от запрошенного клиентом. Для этого используется круговое обращение к серверу. URL-адрес перенаправления, возвращаемый клиенту, отображается в адресной строке браузера, когда клиент отправляет новый запрос для данного ресурса.
Если /resourceперенаправляется на /different-resource, сервер отвечает, что клиенту следует получить ресурс в /different-resource с кодом состояния, указывающим, что такое перенаправление является временным или постоянным.
При перенаправлении запросов на другой URL-адрес можно указать, является ли оно постоянным или временным, предоставив код состояния в ответе:
Код состояния
301 - Moved Permanentlyиспользуется, когда ресурс имеет новый постоянный URL-адрес и все последующие запросы для этого ресурса должны использовать новый URL-адрес. Клиент может кэшировать и повторно использовать отклик при получении кода состояния 301.Код
302 - Foundсостояния используется, когда перенаправление является временным или обычно подлежит изменению. Код состояния 302 указывает клиенту, что не нужно сохранять URL-адрес и использовать его в будущем.
Дополнительные сведения о кодах состояния см. в статье RFC 9110: определения кода состояния.
Переопределение URL-адреса является операцией на стороне сервера для предоставления ресурса с другого адреса ресурса, отличного от запрошенного клиентом. Переопределение URL-адреса не требует кругового обращения к серверу. Переопределенный URL-адрес не возвращается клиенту и не отображается в адресной строке браузера.
Если /resourceперезаписывается в /different-resource, сервер внутренне получает и возвращает ресурс по адресу /different-resource.
Хотя клиент может быть в состоянии получить ресурс по переопределенному URL-адресу, когда клиент отправляет запрос и получает отклик, он не уведомляется о наличии ресурса по переопределенному URL-адресу.
Пример приложения с переопределением URL-адресов
Ознакомьтесь с функциями компонента Middleware для перезаписи URL-адресов с помощью примерного приложения. Это приложение применяет правила перенаправления и переопределения и показывает перенаправленный или переопределенный URL-адрес для нескольких сценариев.
Когда использовать ПО промежуточного слоя для перезаписи URL-адресов
Используйте промежуточное ПО для перезаписи URL-адресов, если следующие подходы вас не устраивают:
- Модуль URL Rewrite для IIS в Windows Server
- Модуль Apache mod_rewrite на сервере Apache Server
- Переопределение URL-адресов в Nginx
Используйте ПО промежуточного слоя для переопределения URL, когда приложение размещено на сервере HTTP.sys.
Основные причины использовать технологии перезаписи URL-адресов на стороне сервера в IIS, Apache и Nginx:
ПО промежуточного слоя не поддерживает все функции этих модулей.
Некоторые функции серверных модулей не работают с проектами ASP.NET Core, например ограничения
IsFileиIsDirectoryдля модуля переопределения IIS. В этих случаях следует использовать ПО промежуточного слоя.Производительность ПО промежуточного слоя, скорее всего, не соответствует производительности модулей.
Тестирование производительности — это единственный способ узнать точно, какой подход больше всего снижает производительность и является ли такое снижение незначительным.
Расширение и параметры
Задайте правила перезаписи и перенаправления URL-адресов, создав экземпляр класса RewriteOptions с методами расширения для каждого из правил перезаписи. Объедините в цепочку несколько правил в том порядке, в котором они должны быть обработаны.
RewriteOptions передаются компоненту-посреднику для переопределения URL-адресов при его добавлении в конвейер обработки запросов с помощью UseRewriter:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
В приведенном выше коде MethodRules — это определяемый пользователем класс. Дополнительные сведения см. в разделе RewriteRules.cs этой статьи.
Перенаправить адрес без www на адрес с www
Три параметра разрешают приложению перенаправлять запросы, отличные от www, на www:
AddRedirectToWwwPermanent: постоянно перенаправлять запрос на поддомен
www, если запрос не относится кwww. Перенаправляет с кодом состояния Status308PermanentRedirect.AddRedirectToWww: перенаправьте запрос на поддомен
www, если входящий запрос не являетсяwww. Перенаправляет, используя код состояния Status307TemporaryRedirect. Перегрузка позволяет предоставить код состояния для ответа. Используйте поле класса StatusCodes для назначения кода состояния.
Перенаправление URL-адреса
Используйте AddRedirect для перенаправления запросов. Первый параметр содержит регулярное выражение .NET (Regex) для сопоставления с путем входящего URL-адреса. Второй параметр — строка замены. Третий параметр (при его наличии) указывает код состояния. Если код состояния не задан, по умолчанию используется код 302 — Found (найдено), указывающий, что ресурс временно перемещен или заменен.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
В браузере с включёнными средствами разработчика выполните запрос к тестовому приложению по пути /redirect-rule/1234/5678. Регулярное выражение сопоставляется с путём запроса в redirect-rule/(.*), а затем этот путь заменяется на /redirected/1234/5678. URL-адрес перенаправления отправляется обратно клиенту с кодом состояния 302 (найдено). Браузер выполняет новый запрос на URL-адрес перенаправления, отображаемый в адресной строке. Поскольку в примере приложения нет правил, соответствующих URL-адресу перенаправления:
- Второй запрос получает от приложения ответ 200 (ОК).
- Текст ответа показывает URL-адрес перенаправления.
При перенаправлении URL-адреса используется круговое обращение к серверу.
Warning
Соблюдайте осторожность при задании правил перенаправления. Правила перенаправления проверяются при каждом запросе к приложению, в том числе после перенаправления. Можно легко случайно создать бесконечный цикл перенаправлений.
Часть выражения, заключенная в скобки, называется группой записи. Точка (.) в выражении означает совпадение с любым символом. Звёздочка (*) означает, что предыдущий символ может встречаться ноль или более раз. Таким образом, два последних сегмента пути URL-адреса, 1234/5678, захватываются группой захвата (.*). Любое значение, указанное в URL-адресе запроса после redirect-rule/, перехватывается этой группой записи.
В строке замены захваченные группы подставляются в строку с помощью знака доллара ($), за которым следует порядковый номер захваченной группы. Первое значение группы записи можно получить с помощью $1, а второе — с помощью $2. После этого эти значения по очереди используются для групп записи в регулярном выражении. В регулярном выражении правила перенаправления в redirect-rule/(.*) есть только одна группа захвата, поэтому в строке замены подставляется только одна группа — $1. Когда применяется правило, URL-адрес становится /redirected/1234/5678.
Попробуйте /redirect-rule/1234/5678 в инструментах разработчика браузера на вкладке «Сеть».
Перенаправление URL-адреса на защищенную конечную точку
Используйте AddRedirectToHttps, чтобы перенаправлять HTTP-запросы на тот же узел и путь с использованием протокола HTTPS. Если код состояния не указан, ПО промежуточного слоя по умолчанию использует значение 302 (найдено). Если порт не указан:
- Для промежуточного ПО по умолчанию используется значение
null. - Схема меняется на
https(протокол HTTPS), и клиент обращается к ресурсу через порт 443.
В следующем примере показано, как задать код 301 - Moved Permanently состояния и изменить порт на порт HTTPS, используемый Kestrel на localhost. В рабочей среде порт HTTPS имеет значение NULL:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
int? localhostHTTPSport = null;
if (app.Environment.IsDevelopment())
{
localhostHTTPSport = Int32.Parse(Environment.GetEnvironmentVariable(
"ASPNETCORE_URLS")!.Split(new Char[] { ':', ';' })[2]);
}
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
// localhostHTTPport not needed for production, used only with localhost.
.AddRedirectToHttps(301, localhostHTTPSport)
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Используйте AddRedirectToHttpsPermanent, чтобы перенаправить небезопасные запросы на тот же узел и путь с использованием безопасного протокола HTTPS через порт 443. ПО промежуточного слоя задает код состояния 301 - Moved Permanently.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Note
Если при перенаправлении на защищённый конечный пункт не требуются дополнительные правила перенаправления, мы рекомендуем использовать компонент middleware для перенаправления на HTTPS. Дополнительные сведения см. в разделе Принудительное использование HTTPS.
В этом примере приложения показано, как использовать AddRedirectToHttps или AddRedirectToHttpsPermanent. Выполните небезопасный HTTP-запрос к приложению по адресу http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz. При проверке перенаправления с HTTP на HTTPS с использованием localhost:
- Используйте URL-адрес HTTP с портом, который отличается от порта URL-адреса HTTPS. URL-адрес HTTP находится в файле
Properties/launchSettings.json. - При удалении
sизhttps://localhost/{port}происходит сбой, так как localhost не отвечает на HTTP на порту HTTPS.
На следующем изображении показан запрос к http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz в инструментах разработчика браузера (F12) с использованием приведенного выше кода:
URL rewrite
Используйте AddRewrite, чтобы создать правило для переопределения URL-адресов. Первый параметр содержит регулярное выражение, соответствующее пути входящего URL-адреса. Второй параметр — строка замены. Третий параметр, skipRemainingRules: {true|false}, указывает промежуточному программному обеспечению, следует ли пропускать дополнительные правила перезаписи, если применяется текущее правило.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Попробуйте повторить запрос к https://redirect6.azurewebsites.net/rewrite-rule/1234/5678.
Символ вставки (^) в начале выражения означает, что сопоставление начинается с начала пути URL.
В предыдущем примере с правилом перенаправления, redirect-rule/(.*), в начале регулярного выражения отсутствует символ ^ (^). Таким образом, для успешного совпадения в пути перед redirect-rule/ могут находиться любые символы.
| Path | Match |
|---|---|
/redirect-rule/1234/5678 |
Yes |
/my-cool-redirect-rule/1234/5678 |
Yes |
/anotherredirect-rule/1234/5678 |
Yes |
Правило переопределения ^rewrite-rule/(\d+)/(\d+) соответствует путям, только если они начинаются с rewrite-rule/. В следующей таблице обратите внимание на разницу в сопоставлении.
| Path | Match |
|---|---|
/rewrite-rule/1234/5678 |
Yes |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
No |
После части выражения ^rewrite-rule/ следуют две группы захвата (\d+)/(\d+).
\d означает соответствие цифре (числу). Знак "плюс" (+) означает соответствие одному или нескольким предшествующим символам. Таким образом, URL-адрес должен содержать число, за которым следует слэш, а затем другое число. Эти группы захвата подставляются в перезаписанный URL-адрес как $1 и $2. Строка замены для правила перезаписи помещает захваченные группы в строку запроса. Запрошенный путь /rewrite-rule/1234/5678 переопределяется, чтобы ресурс можно было получить по адресу /rewritten?var1=1234&var2=5678. Если в исходном запросе присутствует строка запроса, она сохраняется при переопределении URL-адреса.
Чтобы вернуть ресурс, не требуется дополнительный запрос к серверу. Если ресурс существует, он извлекается и возвращается клиенту с кодом состояния 200 (ОК). Так как клиент не перенаправляется, URL-адрес в адресной строке браузера не изменяется. Клиенты не могут узнать, что на сервере произошла операция переопределения URL-адреса.
Советы по повышению производительности при перезаписи URL-адресов и перенаправлении
Чтобы максимально ускорить отклик:
- Расположите правила перезаписи в порядке от наиболее часто срабатывающего правила к наименее часто срабатывающему.
- Используйте
skipRemainingRules: trueпри любой возможности, так как правила сопоставления потребляют много ресурсов и ухудшают время отклика приложения. Пропускать обработку остальных правил, если найдено совпадение и дополнительная обработка правил не требуется.
Warning
Злоумышленник может предоставлять дорогостоящие входные данные для обработки, вызывая RegularExpressionsатаку типа "отказ в обслуживании". ASP.NET API-интерфейсы платформы Core, использующие RegularExpressions время ожидания. Например, время ожидания Regex (_regexTimeout) класса RedirectRule и классом RewriteRule передаются в односекундное время ожидания.
Note
Ссылки в документации на исходный код .NET обычно загружают ветку репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для конкретного релиза, используйте раскрывающийся список Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Apache mod_rewrite (модуль для перезаписи URL на веб-сервере Apache)
Для применения правил mod_rewrite Apache можно использовать AddApacheModRewrite. Убедитесь, что файл правил развертывается вместе с приложением. Дополнительные сведения и примеры правил mod_rewrite см. в статье о правилах mod_rewrite Apache.
StreamReader используется для чтения правил из файла ApacheModRewrite.txt:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Пример приложения перенаправляет запросы из /apache-mod-rules-redirect/(.\*) в /redirected?id=$1. Код состояния ответа: 302 - Found.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Попробуйте повторить запрос к https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234.
Промежуточное ПО Apache поддерживает следующие серверные переменные Apache mod_rewrite:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Note
Ссылки в документации на исходный код .NET обычно загружают ветку репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для конкретного релиза, используйте раскрывающийся список Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Правила модуля переопределения URL-адресов для IIS
Чтобы использовать тот же набор правил, который применяется к модулю переопределения URL-адресов для IIS, используйте AddIISUrlRewrite. Убедитесь, что файл правил развертывается вместе с приложением. Не настраивайте промежуточное ПО на использование файла web.config приложения при работе в IIS на Windows Server. В IIS эти правила нужно хранить за пределами файла приложения web.config, чтобы предотвратить конфликты с модулем переопределения для IIS. Дополнительные сведения и примеры правил модуля переопределения URL-адресов для IIS см. в разделах Использование модуля переопределения URL-адресов 2.0 и Справочник по конфигурации модуля переопределения URL-адресов.
Используется StreamReader для чтения правил из IISUrlRewrite.xml файла правил:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Пример приложения переопределяет запросы с /iis-rules-rewrite/(.*) на /rewritten?id=$1. Клиенту отправляется отклик с кодом состояния 200 (ОК).
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Попробуйте повторить запрос к https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz.
Приложения с активным модулем переопределения IIS с настроенными правилами на уровне сервера, которые нежелательным образом влияют на приложение:
- Рассмотрите возможность отключения модуля IIS URL Rewrite для этого приложения.
- Дополнительные сведения см. в разделе Отключение модулей IIS.
Неподдерживаемые функции
ПО промежуточного слоя не поддерживает следующие функции в модуле переопределения URL-адресов для служб IIS:
- Правила для исходящего трафика
- Пользовательские переменные сервера
- Wildcards
- LogRewrittenUrl
Поддерживаемые переменные сервера
ПО промежуточного слоя поддерживает следующие переменные сервера в модуле переопределения URL-адресов для IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Note
Ссылки в документации на исходный код .NET обычно загружают ветку репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для конкретного релиза, используйте раскрывающийся список Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
IFileProvider можно получить с помощью PhysicalFileProvider. Такой подход может обеспечить большую гибкость в выборе расположения файлов правил перезаписи. Убедитесь, что файлы правил перезаписи развернуты на сервере по указанному пути.
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Правило на основе метода
Используйте Add, чтобы реализовать настраиваемую логику правил в методе.
Add предоставляет RewriteContext, делая возможным использование HttpContext в методах переопределения. Свойство RewriteContext.Result определяет, как осуществляется дополнительная обработка в конвейере. Установите значение одного из полей RuleResult из следующей таблицы.
| Результат перезаписи контекста | Action |
|---|---|
RuleResult.ContinueRules (по умолчанию) |
Продолжение применения правил. |
RuleResult.EndResponse |
Остановка применения правил и отправка отклика. |
RuleResult.SkipRemainingRules |
Прекратите применять правила и передайте контекст следующему промежуточному обработчику. |
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Приложение-пример демонстрирует способ, который перенаправляет запросы к путям, которые заканчиваются на .xml. Когда запрос выполняется для /file.xml:
- Запрос перенаправляется в
/xmlfiles/file.xml. - Код состояния получает значение
301 - Moved Permanently. Когда браузер отправляет новый запрос для/xmlfiles/file.xml, промежуточное ПО для статических файлов обслуживает файл клиенту из папки wwwroot/xmlfiles. Для перенаправления необходимо явно указать код состояния ответа. В противном случае возвращается код состояния 200 (ОК) и перенаправление на стороне клиента не происходит.
RewriteRules.cs:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")) ||
request.Path.Value==null)
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Этот подход также переопределяет запросы. В примере приложения показано переопределение пути для любого запроса текстового файла, чтобы отправить текстовый файл file.txt из папки wwwroot. ПО промежуточного слоя статических файлов предоставляет файл по обновленному пути запроса:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
RewriteRules.cs:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value != null &&
request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Правило на основе IRule
Используйте Add, чтобы использовать собственную логику правил в классе, реализующем интерфейс IRule.
IRule позволяет более гибко применять правила, основанные на методах. Класс реализации может включать конструктор, который позволяет передавать параметры для метода ApplyRule.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Значения параметров в примере приложения для extension и newPath проверяются на соответствие нескольким условиям. В extension должно содержаться значение .png, .jpg или .gif. Если newPath недопустим, возникает исключение ArgumentException. Если запрос выполняется для image.png, запрос перенаправляется к /png-images/image.png. Если запрос выполняется для image.jpg, запрос перенаправляется к /jpg-images/image.jpg. Для кода состояния устанавливается значение 301 - Moved Permanently, а также задается значение context.Result, чтобы остановить обработку правил и отправить ответ.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)) ||
request.Path.Value == null)
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Try:
- Запрос PNG:
https://redirect6.azurewebsites.net/image.png - Запрос JPG:
https://redirect6.azurewebsites.net/image.jpg
Примеры регулярных выражений
| Goal | Пример строки регулярного выражения Пример сопоставления |
Строка замены & Пример вывода |
|---|---|---|
| Переопределение пути в строке запроса | ^path/(.*)/(.*)/path/abc/123 |
path?var1=$1&var2=$2/path?var1=abc&var2=123 |
| Удалить завершающий слеш | ^path2/(.*)/$/path2/xyz/ |
$1/path2/xyz |
| Добавление косой черты в конце | ^path3/(.*[^/])$/path3/xyz |
$1//path3/xyz/ |
| Избегайте переписывания конкретных запросов |
^(.*)(?<!\.axd)$ или ^(?!.*\.axd$)(.*)$Да: /path4/resource.htmНет: /path4/resource.axd |
rewritten/$1/rewritten/resource.htm/resource.axd |
| Переупорядочение сегментов URL-адреса | path5/(.*)/(.*)/(.*)path5/1/2/3 |
path5/$3/$2/$1path5/3/2/1 |
| Замена сегмента URL-адреса | ^path6/(.*)/segment2/(.*)^path6/segment1/segment2/segment3 |
path6/$1/replaced/$2/path6/segment1/replaced/segment3 |
В ссылках в предыдущей таблице используется следующий код, развернутый в Azure:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
// Rewrite path to QS.
.AddRewrite(@"^path/(.*)/(.*)", "path?var1=$1&var2=$2",
skipRemainingRules: true)
// Skip trailing slash.
.AddRewrite(@"^path2/(.*)/$", "path2/$1",
skipRemainingRules: true)
// Enforce trailing slash.
.AddRewrite(@"^path3/(.*[^/])$", "path3/$1/",
skipRemainingRules: true)
// Avoid rewriting specific requests.
.AddRewrite(@"^path4/(.*)(?<!\.axd)$", "rewritten/$1",
skipRemainingRules: true)
// Rearrange URL segments
.AddRewrite(@"^path5/(.*)/(.*)/(.*)", "path5/$3/$2/$1",
skipRemainingRules: true)
// Replace a URL segment
.AddRewrite(@"^path6/(.*)/segment2/(.*)", "path6/$1/replaced/$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
В большинстве приведенных выше примеров регулярных выражений литерал path используется для создания уникальных тестируемых правил переопределения для развернутого примера. Обычно регулярное выражение не содержит path. Например, см. таблицу с примерами регулярных выражений.
Этот документ содержит вводные сведения о переопределении URL-адресов и инструкции по использованию ПО промежуточного слоя для переопределения URL-адресов в приложениях ASP.NET Core.
Переопределение URL-адресов представляет собой изменение URL-адресов запросов на основе одного или нескольких предопределенных правил. Переопределение URL-адресов создает абстракцию между расположениями ресурсов и их адресами, позволяя убрать тесную связь между ними. Существует несколько сценариев, где может пригодиться переопределение URL-адресов:
- Временное или постоянное перемещение или замещение ресурсов сервера с сохранением стабильных указателей для этих ресурсов.
- Разделение обработки запросов между разными приложениями или разными областями одного приложения.
- Удаление, добавление или переупорядочение сегментов URL-адресов для входящих запросов.
- Оптимизация общедоступных URL-адресов в целях оптимизации для поисковых систем (SEO).
- Разрешение использования понятных общедоступных URL-адресов, чтобы помочь посетителям прогнозировать содержимое, возвращаемое в результате запроса ресурса.
- Перенаправление небезопасных запросов на защищенные конечные точки.
- Запрет вставки прямых ссылок, когда внешний сайт использует статический ресурс, размещенный на другом сайте, привязывая ресурс к своему содержимому.
Note
Переопределение URL-адресов может снижать производительность приложения. Следует по возможности ограничить число и сложность правил.
Просмотреть или скачать образец кода (описание загрузки)
Перенаправление и переопределение URL-адресов
Разница между перенаправлением и переопределением URL-адресов может показаться незначительной, но она оказывает существенное влияние на предоставление ресурсов клиентам. ПО промежуточного слоя для переопределения URL-адресов в ASP.NET Core удовлетворяет потребность в обеих этих функциях.
Перенаправление URL-адресов является операцией на стороне клиента, которая предписывает клиенту обратиться к ресурсу по другому адресу, отличному от запрошенного клиентом. Для этого используется круговое обращение к серверу. URL-адрес перенаправления, возвращаемый клиенту, отображается в адресной строке браузера, когда клиент отправляет новый запрос для данного ресурса.
Если /resourceперенаправляется на /different-resource, сервер отвечает, что клиенту следует получить ресурс в /different-resource с кодом состояния, указывающим, что такое перенаправление является временным или постоянным.
При перенаправлении запросов на другой URL-адрес можно указать, является ли оно постоянным или временным, предоставив код состояния в ответе:
Код состояния
301 - Moved Permanentlyиспользуется, когда ресурс имеет новый постоянный URL-адрес и вы хотите сообщить клиенту, что все последующие запросы для этого ресурса должны использовать новый URL-адрес. Клиент может кэшировать и повторно использовать отклик при получении кода состояния 301.Код состояния 302 (найдено) используется, когда перенаправление является временным или может меняться. Код состояния 302 указывает клиенту, что не нужно сохранять URL-адрес и использовать его в будущем.
Дополнительные сведения о кодах состояния см. в статье RFC 9110: определения кода состояния.
Переопределение URL-адреса является операцией на стороне сервера для предоставления ресурса с другого адреса ресурса, отличного от запрошенного клиентом. Переопределение URL-адреса не требует кругового обращения к серверу. Переопределенный URL-адрес не возвращается клиенту и не отображается в адресной строке браузера.
Если /resourceперезаписывается в /different-resource, сервер на внутреннем уровне получает и возвращает ресурс по адресу /different-resource.
Хотя клиент может быть в состоянии получить ресурс по переопределенному URL-адресу, когда клиент отправляет запрос и получает отклик, он не уведомляется о наличии ресурса по переопределенному URL-адресу.
Пример приложения с переопределением URL-адресов
Вы можете изучить возможности компонента промежуточного ПО для перезаписи URL-адресов с помощью примерного приложения. Это приложение применяет правила перенаправления и переопределения и показывает перенаправленный или переопределенный URL-адрес для нескольких сценариев.
Когда использовать промежуточное ПО для перезаписи URL-адресов
Используйте ПО промежуточного слоя для переопределения URL-адресов, если невозможно использовать следующие подходы:
- Модуль перезаписи URL-адресов в IIS на Windows Server
- Модуль Apache mod_rewrite на сервере Apache Server
- Переопределение URL-адресов в Nginx
Используйте ПО промежуточного слоя для перезаписи URL, когда приложение размещается на сервере HTTP.sys.
Основные причины использования технологий перезаписи URL-адресов на стороне сервера в IIS, Apache и Nginx:
ПО промежуточного слоя не поддерживает все функции этих модулей.
Некоторые функции серверных модулей не работают с проектами ASP.NET Core, например ограничения
IsFileиIsDirectoryдля модуля переопределения IIS. В этих случаях следует использовать ПО промежуточного слоя.Производительность ПО промежуточного слоя, скорее всего, не соответствует производительности модулей.
Тестирование производительности — это единственный способ узнать точно, какой подход больше всего снижает производительность или является ли такое снижение незначительным.
Package
ПО промежуточного слоя перезаписи URL-адресов предоставляется пакетом Microsoft.AspNetCore.Rewrite, который неявно включается в приложения ASP.NET Core.
Расширение и параметры
Настройте правила перезаписи и перенаправления URL-адресов, создав экземпляр класса RewriteOptions и используя методы расширения для каждого из правил перезаписи. Несколько правил можно объединить в цепочку в том порядке, в котором они должны обрабатываться.
RewriteOptions передаются в ПО промежуточного слоя для переопределения URL-адресов по мере его добавления в конвейер запросов с помощью UseRewriter:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Перенаправить адреса без www на www
Три параметра разрешают приложению перенаправлять запросы, отличные от www, на www:
AddRedirectToWwwPermanent: Постоянно перенаправлять запрос на поддомен
www, если запрос не относится к типуwww. Перенаправляет, используя код состояния Status308PermanentRedirect.AddRedirectToWww: Перенаправьте запрос на поддомен
www, если входящий запрос неwww. Перенаправляет с кодом состояния Status307TemporaryRedirect. Перегрузка позволяет указать код состояния в ответе. Используйте поле класса StatusCodes для назначения кода состояния.
Перенаправление URL-адреса
Используйте AddRedirect для перенаправления запросов. Первый параметр содержит регулярное выражение, соответствующее пути входящего URL-адреса. Второй параметр — строка замены. Третий параметр (при его наличии) указывает код состояния. Если код состояния не задан, по умолчанию используется код 302 (найдено), указывающий, что ресурс временно перемещен или заменен.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
В браузере с включёнными инструментами разработчика отправьте запрос к тестовому приложению по пути /redirect-rule/1234/5678. Регулярное выражение соответствует пути запроса в redirect-rule/(.*), и этот путь заменяется на /redirected/1234/5678. URL-адрес перенаправления отправляется обратно клиенту с кодом состояния 302 (найдено). Браузер выполняет новый запрос на URL-адрес перенаправления, отображаемый в адресной строке. Поскольку в примере приложения нет правил, соответствующих URL-адресу перенаправления:
- Второй запрос получает от приложения ответ 200 (ОК).
- Текст ответа показывает URL-адрес перенаправления.
При перенаправлении URL-адреса используется круговое обращение к серверу.
Warning
Соблюдайте осторожность при задании правил перенаправления. Правила перенаправления проверяются при каждом запросе к приложению, в том числе после перенаправления. Можно легко случайно создать бесконечный цикл перенаправлений.
Исходный запрос: /redirect-rule/1234/5678
Часть выражения, заключенная в скобки, называется группой записи. Точка (.) в выражении означает совпадение с любым символом. Звездочка (*) обозначает повторение предыдущего символа ноль или более раз. Таким образом, два последних сегмента пути URL-адреса, 1234/5678, захватываются группой захвата (.*). Любое значение, указанное в URL-адресе запроса после redirect-rule/, перехватывается этой группой записи.
В строке замены захваченные группы подставляются в строку с помощью знака доллара ($), за которым следует порядковый номер захвата. Первое значение группы записи получается с помощью $1, второе — с помощью $2, после чего они продолжают по очереди использоваться для групп записи в регулярном выражении. В регулярном выражении правила перенаправления в приложении-примере есть только одна захватывающая группа, поэтому в строку замены подставляется только одна группа — $1. Когда применяется правило, URL-адрес становится /redirected/1234/5678.
Перенаправление URL-адреса на защищенную конечную точку
Используйте AddRedirectToHttps, чтобы перенаправлять HTTP-запросы на тот же узел и путь с использованием протокола HTTPS. Если код состояния не указан, ПО промежуточного слоя по умолчанию использует значение 302 (найдено). Если порт не указан:
- Для промежуточного ПО по умолчанию используется значение
null. - Схема меняется на
https(протокол HTTPS), и клиент обращается к ресурсу через порт 443.
В следующем примере показано, как задать код 301 - Moved Permanently состояния и изменить порт на 5001.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Используйте AddRedirectToHttpsPermanent, чтобы перенаправить небезопасные запросы на тот же узел и путь с использованием безопасного протокола HTTPS через порт 443. ПО промежуточного слоя задает код состояния 301 - Moved Permanently.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Note
При перенаправлении на защищённый URL-адрес, если не требуются дополнительные правила перенаправления, рекомендуется использовать промежуточное ПО перенаправления на HTTPS. Дополнительные сведения см. в разделе Обязательное использование HTTPS.
Пример приложения позволяет продемонстрировать использование AddRedirectToHttps или AddRedirectToHttpsPermanent. Добавьте этот метод расширения в RewriteOptions. Выполните небезопасный запрос к приложению по любому URL-адресу. Закройте предостережение системы безопасности о том, что самозаверяющий сертификат не является доверенным, или создайте исключение, чтобы сделать сертификат доверенным.
Исходный запрос с использованием AddRedirectToHttps(301, 5001): http://localhost:5000/secure
Исходный запрос с использованием AddRedirectToHttpsPermanent: http://localhost:5000/secure
URL rewrite
Используйте AddRewrite, чтобы создать правило для переопределения URL-адресов. Первый параметр содержит регулярное выражение, соответствующее пути входящего URL-адреса. Второй параметр — строка замены. Третий параметр, skipRemainingRules: {true|false}, указывает промежуточному ПО, следует ли пропустить дополнительные правила перезаписи, если применяется текущее правило.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Исходный запрос: /rewrite-rule/1234/5678
Символ каретки (^) в начале выражения означает, что сопоставление начинается с начала пути URL-адреса.
В предыдущем примере с правилом перенаправления, redirect-rule/(.*), в начале регулярного выражения отсутствует символ каретки (^). Таким образом, для успешного совпадения в пути перед redirect-rule/ могут находиться любые символы.
| Path | Match |
|---|---|
/redirect-rule/1234/5678 |
Yes |
/my-cool-redirect-rule/1234/5678 |
Yes |
/anotherredirect-rule/1234/5678 |
Yes |
Правило переопределения ^rewrite-rule/(\d+)/(\d+) соответствует путям, только если они начинаются с rewrite-rule/. В следующей таблице обратите внимание на разницу в сопоставлении.
| Path | Match |
|---|---|
/rewrite-rule/1234/5678 |
Yes |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
No |
После части ^rewrite-rule/ выражения стоят две группы записи (\d+)/(\d+).
\d означает соответствие цифре (числу). Знак "плюс" (+) означает соответствие одному или нескольким предшествующим символам. Таким образом, URL должен содержать число, за которым следует наклонная черта, а затем другое число. Эти группы захвата подставляются в перезаписанный URL-адрес как $1 и $2. Строка замены для правила перезаписи подставляет захваченные группы в строку запроса. Запрошенный путь /rewrite-rule/1234/5678 переопределяется, чтобы ресурс можно было получить по адресу /rewritten?var1=1234&var2=5678. Если в исходном запросе присутствует строка запроса, она сохраняется при переопределении URL-адреса.
Для получения ресурса не требуется дополнительный запрос к серверу. Если ресурс существует, он извлекается и возвращается клиенту с кодом состояния 200 (ОК). Так как клиент не перенаправляется, URL-адрес в адресной строке браузера не изменяется. Клиенты не могут узнать, что на сервере произошла операция переопределения URL-адреса.
Note
Используйте skipRemainingRules: true при любой возможности, так как правила сопоставления потребляют много ресурсов и ухудшают время отклика приложения. Чтобы максимально ускорить отклик приложения:
- Расположите правила перезаписи в порядке от наиболее часто срабатывающего правила к наименее часто срабатывающему.
- Пропускать обработку оставшихся правил, если найдено совпадение и дальнейшая обработка правил не требуется.
Apache mod_rewrite (модуль для перезаписи URL на веб-сервере Apache)
Для применения правил mod_rewrite Apache можно использовать AddApacheModRewrite. Убедитесь, что файл правил развертывается вместе с приложением. Дополнительные сведения и примеры правил mod_rewrite см. в статье о правилах mod_rewrite Apache.
StreamReader используется для чтения правил из файла ApacheModRewrite.txt:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Пример приложения перенаправляет запросы из /apache-mod-rules-redirect/(.\*) в /redirected?id=$1. Код состояния ответа — 302 - Найден.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Исходный запрос: /apache-mod-rules-redirect/1234
Промежуточное ПО поддерживает следующие серверные переменные Apache mod_rewrite:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Правила модуля переопределения URL-адресов для IIS
Чтобы использовать тот же набор правил, который применяется к модулю переопределения URL-адресов для IIS, используйте AddIISUrlRewrite. Убедитесь, что файл правил развертывается вместе с приложением. Не настраивайте промежуточное ПО на использование файла web.config приложения при работе в IIS Windows Server. В IIS эти правила нужно хранить за пределами файла приложения web.config, чтобы предотвратить конфликты с модулем переопределения для IIS. Дополнительные сведения и примеры правил модуля переопределения URL-адресов для IIS см. в разделах Использование модуля переопределения URL-адресов 2.0 и Справочник по конфигурации модуля переопределения URL-адресов.
Используется StreamReader для чтения правил из IISUrlRewrite.xml файла правил:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Пример приложения переопределяет запросы с /iis-rules-rewrite/(.*) на /rewritten?id=$1. Клиенту отправляется отклик с кодом состояния 200 (ОК).
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Исходный запрос: /iis-rules-rewrite/1234
Если у вас активен модуль IIS Rewrite с настроенными правилами уровня сервера, которые могут нежелательным образом повлиять на ваше приложение, вы можете отключить модуль IIS Rewrite для конкретного приложения. Дополнительные сведения см. в разделе Отключение модулей IIS.
Неподдерживаемые функции
ПО промежуточного слоя не поддерживает следующие функции в модуле переопределения URL-адресов для служб IIS:
- Правила для исходящего трафика
- Пользовательские переменные сервера
- Wildcards
- LogRewrittenUrl
Поддерживаемые переменные сервера
ПО промежуточного слоя поддерживает следующие переменные сервера в модуле переопределения URL-адресов для IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Note
Можно также получить IFileProvider с помощью PhysicalFileProvider. Этот подход может обеспечить большую гибкость в выборе расположения файлов правил перезаписи. Убедитесь, что ваши файлы правил перезаписи развернуты на сервере по пути, который вы укажете.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Правило на основе метода
Используйте Add, чтобы реализовать собственную логику правил в методе.
Add открывает доступ к RewriteContext, который делает HttpContext доступным для использования в вашем методе.
RewriteContext.Result определяет, как осуществляется дополнительная обработка в конвейере. Установите значение одного из полей RuleResult из следующей таблицы.
| Результат перезаписи контекста | Action |
|---|---|
RuleResult.ContinueRules (по умолчанию) |
Продолжение применения правил. |
RuleResult.EndResponse |
Остановка применения правил и отправка отклика. |
RuleResult.SkipRemainingRules |
Прекратите применять правила и передайте контекст следующему промежуточному обработчику. |
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Пример приложения демонстрирует метод, который перенаправляет запросы к путям, оканчивающимся на .xml. Если запрос выполняется для /file.xml, запрос перенаправляется к /xmlfiles/file.xml. Код состояния получает значение 301 - Moved Permanently. Когда браузер отправляет новый запрос для /xmlfiles/file.xml, промежуточное ПО для статических файлов обслуживает файл клиенту из папки wwwroot/xmlfiles. Для перенаправления необходимо явно указать код состояния ответа. В противном случае возвращается код состояния 200 (ОК) и перенаправление на стороне клиента не происходит.
RewriteRules.cs:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Этот подход также переопределяет запросы. В примере приложения показано переопределение пути для любого запроса текстового файла, чтобы отправить текстовый файл file.txt из папки wwwroot. ПО промежуточного слоя статических файлов предоставляет файл по обновленному пути запроса:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Правило на основе IRule
Используйте Add, чтобы использовать собственную логику правил в классе, реализующем интерфейс IRule.
IRule позволяет более гибко применять правила, основанные на методах. Класс реализации может включать конструктор, который позволяет передавать параметры для метода ApplyRule.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Значения параметров в примере приложения для extension и newPath проверяются на соответствие нескольким условиям.
extension должен содержать одно из значений: .png, .jpg или .gif. Если newPath недопустим, возникает исключение ArgumentException. Если запрос выполняется для image.png, запрос перенаправляется к /png-images/image.png. Если запрос выполняется для image.jpg, запрос перенаправляется к /jpg-images/image.jpg. Для кода состояния устанавливается значение 301 - Moved Permanently, а также задается значение context.Result, чтобы остановить обработку правил и отправить ответ.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Исходный запрос: /image.png
Исходный запрос: /image.jpg
Примеры регулярных выражений
| Goal | Пример строки регулярного выражения Пример сопоставления |
Строка замены & Пример вывода |
|---|---|---|
| Переопределение пути в строке запроса | ^path/(.*)/(.*)/path/abc/123 |
path?var1=$1&var2=$2/path?var1=abc&var2=123 |
| Удалить завершающий слеш | (.*)/$/path/ |
$1/path |
| Добавление косой черты в конце | (.*[^/])$/path |
$1//path/ |
| Избегайте переписывания конкретных запросов |
^(.*)(?<!\.axd)$ или ^(?!.*\.axd$)(.*)$Да: /resource.htmНет: /resource.axd |
rewritten/$1/rewritten/resource.htm/resource.axd |
| Переупорядочение сегментов URL-адреса | path/(.*)/(.*)/(.*)path/1/2/3 |
path/$3/$2/$1path/3/2/1 |
| Замена сегмента URL-адреса | ^(.*)/segment2/(.*)/segment1/segment2/segment3 |
$1/replaced/$2/segment1/replaced/segment3 |
Этот документ содержит вводные сведения о переопределении URL-адресов и инструкции по использованию ПО промежуточного слоя для переопределения URL-адресов в приложениях ASP.NET Core.
Переопределение URL-адресов представляет собой изменение URL-адресов запросов на основе одного или нескольких предопределенных правил. Переопределение URL-адресов создает абстракцию между расположениями ресурсов и их адресами, позволяя убрать тесную связь между ними. Существует несколько сценариев, где может пригодиться переопределение URL-адресов:
- Временное или постоянное перемещение или замещение ресурсов сервера с сохранением стабильных указателей для этих ресурсов.
- Разделение обработки запросов между разными приложениями или разными областями одного приложения.
- Удаление, добавление или переупорядочение сегментов URL-адресов для входящих запросов.
- Оптимизация общедоступных URL-адресов в целях оптимизации для поисковых систем (SEO).
- Разрешение использования понятных общедоступных URL-адресов, чтобы помочь посетителям прогнозировать содержимое, возвращаемое в результате запроса ресурса.
- Перенаправление небезопасных запросов на защищенные конечные точки.
- Запрет вставки прямых ссылок, когда внешний сайт использует статический ресурс, размещенный на другом сайте, привязывая ресурс к своему содержимому.
Note
Переопределение URL-адресов может снижать производительность приложения. Следует по возможности ограничить число и сложность правил.
Просмотреть или скачать образец кода (описание загрузки)
Перенаправление и переопределение URL-адресов
Разница между перенаправлением и переопределением URL-адресов может показаться незначительной, но она оказывает существенное влияние на предоставление ресурсов клиентам. ПО промежуточного слоя для переопределения URL-адресов в ASP.NET Core удовлетворяет потребность в обеих этих функциях.
Перенаправление URL-адресов является операцией на стороне клиента, которая предписывает клиенту обратиться к ресурсу по другому адресу, отличному от запрошенного клиентом. Для этого используется круговое обращение к серверу. URL-адрес перенаправления, возвращаемый клиенту, отображается в адресной строке браузера, когда клиент отправляет новый запрос для данного ресурса.
Если /resourceперенаправляется на /different-resource, сервер отвечает, что клиенту следует получить ресурс в /different-resource с кодом состояния, указывающим, что такое перенаправление является временным или постоянным.
При перенаправлении запросов на другой URL-адрес можно указать, является ли оно постоянным или временным, предоставив код состояния в ответе:
Код состояния
301 - Moved Permanentlyиспользуется, когда ресурс имеет новый постоянный URL-адрес и вы хотите сообщить клиенту, что все последующие запросы для этого ресурса должны использовать новый URL-адрес. Клиент может кэшировать и повторно использовать отклик при получении кода состояния 301.Код состояния 302 (найдено) используется, когда перенаправление является временным или может меняться. Код состояния 302 указывает клиенту, что не нужно сохранять URL-адрес и использовать его в будущем.
Дополнительные сведения о кодах состояния см. в статье RFC 9110: определения кода состояния.
Переопределение URL-адреса является операцией на стороне сервера для предоставления ресурса с другого адреса ресурса, отличного от запрошенного клиентом. Переопределение URL-адреса не требует кругового обращения к серверу. Переопределенный URL-адрес не возвращается клиенту и не отображается в адресной строке браузера.
Если /resourceперезаписывается в /different-resource, сервер на внутреннем уровне получает и возвращает ресурс по адресу /different-resource.
Хотя клиент может быть в состоянии получить ресурс по переопределенному URL-адресу, когда клиент отправляет запрос и получает отклик, он не уведомляется о наличии ресурса по переопределенному URL-адресу.
Пример приложения с переопределением URL-адресов
Вы можете изучить возможности компонента промежуточного ПО для перезаписи URL-адресов с помощью примерного приложения. Это приложение применяет правила перенаправления и переопределения и показывает перенаправленный или переопределенный URL-адрес для нескольких сценариев.
Когда использовать промежуточное ПО для перезаписи URL-адресов
Используйте ПО промежуточного слоя для переопределения URL-адресов, если невозможно использовать следующие подходы:
- Модуль перезаписи URL-адресов в IIS на Windows Server
- Модуль Apache mod_rewrite на сервере Apache Server
- Переопределение URL-адресов в Nginx
Кроме того, используйте ПО промежуточного слоя, когда приложение размещается на сервере HTTP.sys (который раньше назывался WebListener).
Основные причины использования технологий перезаписи URL-адресов на стороне сервера в IIS, Apache и Nginx:
ПО промежуточного слоя не поддерживает все функции этих модулей.
Некоторые функции серверных модулей не работают с проектами ASP.NET Core, например ограничения
IsFileиIsDirectoryдля модуля переопределения IIS. В этих случаях следует использовать ПО промежуточного слоя.Производительность ПО промежуточного слоя, скорее всего, не соответствует производительности модулей.
Тестирование производительности — это единственный способ узнать точно, какой подход больше всего снижает производительность или является ли такое снижение незначительным.
Package
Чтобы включить ПО промежуточного слоя в проект, добавьте ссылки на пакет в метапакет Microsoft.AspNetCore.App в файле проекта, который содержит пакет Microsoft.AspNetCore.Rewrite.
Если метапакет Microsoft.AspNetCore.App не используется, добавьте ссылку на проект в пакет Microsoft.AspNetCore.Rewrite.
Расширение и параметры
Настройте правила перезаписи и перенаправления URL-адресов, создав экземпляр класса RewriteOptions и используя методы расширения для каждого из правил перезаписи. Несколько правил можно объединить в цепочку в том порядке, в котором они должны обрабатываться.
RewriteOptions передаются в ПО промежуточного слоя для переопределения URL-адресов по мере его добавления в конвейер запросов с помощью UseRewriter:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Перенаправить адреса без www на www
Три параметра разрешают приложению перенаправлять запросы, отличные от www, на www:
AddRedirectToWwwPermanent: Постоянно перенаправлять запрос на поддомен
www, если запрос не относится к типуwww. Перенаправляет, используя код состояния Status308PermanentRedirect.AddRedirectToWww: Перенаправьте запрос на поддомен
www, если входящий запрос неwww. Перенаправляет с кодом состояния Status307TemporaryRedirect. Перегрузка позволяет указать код состояния в ответе. Используйте поле класса StatusCodes для назначения кода состояния.
Перенаправление URL-адреса
Используйте AddRedirect для перенаправления запросов. Первый параметр содержит регулярное выражение, соответствующее пути входящего URL-адреса. Второй параметр — строка замены. Третий параметр (при его наличии) указывает код состояния. Если код состояния не задан, по умолчанию используется код 302 (найдено), указывающий, что ресурс временно перемещен или заменен.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
В браузере с включёнными инструментами разработчика отправьте запрос к тестовому приложению по пути /redirect-rule/1234/5678. Регулярное выражение соответствует пути запроса в redirect-rule/(.*), и этот путь заменяется на /redirected/1234/5678. URL-адрес перенаправления отправляется обратно клиенту с кодом состояния 302 (найдено). Браузер выполняет новый запрос на URL-адрес перенаправления, отображаемый в адресной строке. Поскольку в примере приложения нет правил, соответствующих URL-адресу перенаправления:
- Второй запрос получает от приложения ответ 200 (ОК).
- Текст ответа показывает URL-адрес перенаправления.
При перенаправлении URL-адреса используется круговое обращение к серверу.
Warning
Соблюдайте осторожность при задании правил перенаправления. Правила перенаправления проверяются при каждом запросе к приложению, в том числе после перенаправления. Можно легко случайно создать бесконечный цикл перенаправлений.
Исходный запрос: /redirect-rule/1234/5678
Часть выражения, заключенная в скобки, называется группой записи. Точка (.) в выражении означает совпадение с любым символом. Звездочка (*) означает, что предыдущий символ может встречаться ноль или более раз. Таким образом, два последних сегмента пути URL-адреса, 1234/5678, захватываются группой захвата (.*). Любое значение, указанное в URL-адресе запроса после redirect-rule/, перехватывается этой группой записи.
В строке замены захваченные группы подставляются в строку с помощью знака доллара ($), за которым следует порядковый номер группы захвата. Первое значение группы захвата получают с помощью $1, второе — с помощью $2, и далее они идут последовательно для групп захвата в вашем регулярном выражении. В регулярном выражении правила перенаправления в примере приложения есть только одна захватывающая группа, поэтому в строке замены подставляется только одна группа — $1. Когда применяется правило, URL-адрес становится /redirected/1234/5678.
Перенаправление URL-адреса на защищённую конечную точку
Используйте AddRedirectToHttps, чтобы перенаправлять HTTP-запросы на тот же узел и путь с использованием протокола HTTPS. Если код состояния не указан, ПО промежуточного слоя по умолчанию использует значение 302 (найдено). Если порт не указан:
- По умолчанию используется промежуточное ПО
null. - Схема меняется на
https(протокол HTTPS), и клиент обращается к ресурсу через порт 443.
В следующем примере показано, как задать код 301 - Moved Permanently состояния и изменить порт на 5001.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Используйте AddRedirectToHttpsPermanent, чтобы перенаправить небезопасные запросы на тот же узел и путь с использованием безопасного протокола HTTPS через порт 443. ПО промежуточного слоя задает код состояния 301 - Moved Permanently.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Note
При перенаправлении на защищённый URL-адрес, если не требуются дополнительные правила перенаправления, рекомендуется использовать промежуточное ПО перенаправления HTTPS. Дополнительные сведения см. в разделе Обязательное использование HTTPS.
Пример приложения позволяет продемонстрировать использование AddRedirectToHttps или AddRedirectToHttpsPermanent. Добавьте этот метод расширения в RewriteOptions. Выполните небезопасный запрос к приложению по любому URL-адресу. Закройте предостережение системы безопасности о том, что самозаверяющий сертификат не является доверенным, или создайте исключение, чтобы сделать сертификат доверенным.
Исходный запрос с использованием AddRedirectToHttps(301, 5001): http://localhost:5000/secure
Исходный запрос с использованием AddRedirectToHttpsPermanent: http://localhost:5000/secure
URL rewrite
Используйте AddRewrite, чтобы создать правило для переопределения URL-адресов. Первый параметр содержит регулярное выражение, соответствующее пути входящего URL-адреса. Второй параметр — строка замены. Третий параметр skipRemainingRules: {true|false}, указывает промежуточному ПО, следует ли пропускать дополнительные правила перезаписи, если текущее правило применяется.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Исходный запрос: /rewrite-rule/1234/5678
Символ каретки (^) в начале выражения означает, что сопоставление начинается с начала пути URL.
В предыдущем примере с правилом перенаправления redirect-rule/(.*) в начале регулярного выражения нет символа каретки (^). Таким образом, для успешного совпадения в пути перед redirect-rule/ могут находиться любые символы.
| Path | Match |
|---|---|
/redirect-rule/1234/5678 |
Yes |
/my-cool-redirect-rule/1234/5678 |
Yes |
/anotherredirect-rule/1234/5678 |
Yes |
Правило переопределения ^rewrite-rule/(\d+)/(\d+) соответствует путям, только если они начинаются с rewrite-rule/. В следующей таблице обратите внимание на разницу в сопоставлении.
| Path | Match |
|---|---|
/rewrite-rule/1234/5678 |
Yes |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
No |
После части выражения ^rewrite-rule/ следуют две группы захвата (\d+)/(\d+).
\d означает соответствует цифре (числу). Знак "плюс" (+) означает соответствие одному или нескольким предшествующим символам. Таким образом, URL должен содержать число, за которым следует символ /, а затем другое число. Эти группы захвата подставляются в перезаписанный URL-адрес как $1 и $2. Строка замены для правила перезаписи подставляет захваченные группы в строку запроса. Запрошенный путь /rewrite-rule/1234/5678 переопределяется, чтобы ресурс можно было получить по адресу /rewritten?var1=1234&var2=5678. Если в исходном запросе присутствует строка запроса, она сохраняется при переопределении URL-адреса.
Для получения ресурса не требуется отправлять запрос на сервер и получать от него ответ. Если ресурс существует, он извлекается и возвращается клиенту с кодом состояния 200 (ОК). Так как клиент не перенаправляется, URL-адрес в адресной строке браузера не изменяется. Клиенты не могут узнать, что на сервере произошла операция переопределения URL-адреса.
Note
Используйте skipRemainingRules: true при любой возможности, так как правила сопоставления потребляют много ресурсов и ухудшают время отклика приложения. Чтобы максимально ускорить отклик приложения:
- Расположите правила перезаписи в порядке от наиболее часто срабатывающего правила к наименее часто срабатывающему.
- Пропускать обработку оставшихся правил при совпадении, если не требуется дальнейшая обработка правил.
Apache mod_rewrite (модуль для перезаписи URL на веб-сервере Apache)
Для применения правил mod_rewrite Apache можно использовать AddApacheModRewrite. Убедитесь, что файл правил развертывается вместе с приложением. Дополнительные сведения и примеры правил mod_rewrite см. в статье о правилах mod_rewrite Apache.
StreamReader используется для чтения правил из файла ApacheModRewrite.txt:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Пример приложения перенаправляет запросы из /apache-mod-rules-redirect/(.\*) в /redirected?id=$1. Код состояния ответа — 302 — Найдено.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Исходный запрос: /apache-mod-rules-redirect/1234
Промежуточное ПО поддерживает следующие серверные переменные Apache mod_rewrite:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Правила модуля переопределения URL-адресов для IIS
Чтобы использовать тот же набор правил, который применяется к модулю переопределения URL-адресов для IIS, используйте AddIISUrlRewrite. Убедитесь, что файл правил развертывается вместе с приложением. Не настраивайте промежуточное ПО на использование файла web.config приложения при работе в IIS на Windows Server. В IIS эти правила нужно хранить за пределами файла приложения web.config, чтобы предотвратить конфликты с модулем переопределения для IIS. Дополнительные сведения и примеры правил модуля переопределения URL-адресов для IIS см. в разделах Использование модуля переопределения URL-адресов 2.0 и Справочник по конфигурации модуля переопределения URL-адресов.
Используется StreamReader для чтения правил из IISUrlRewrite.xml файла правил:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Пример приложения переопределяет запросы с /iis-rules-rewrite/(.*) на /rewritten?id=$1. Клиенту отправляется отклик с кодом состояния 200 (ОК).
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Исходный запрос: /iis-rules-rewrite/1234
Если у вас активен модуль IIS Rewrite и в нём настроены правила уровня сервера, которые могут нежелательным образом повлиять на ваше приложение, вы можете отключить модуль IIS Rewrite для этого приложения. Дополнительные сведения см. в разделе Отключение модулей IIS.
Неподдерживаемые функции
ПО промежуточного слоя, выпущенное вместе с ASP.NET Core 2.x, не поддерживает следующие функции в модуле переопределения URL-адресов для IIS:
- Правила для исходящего трафика
- Пользовательские переменные сервера
- Wildcards
- LogRewrittenUrl
Поддерживаемые переменные сервера
ПО промежуточного слоя поддерживает следующие переменные сервера в модуле переопределения URL-адресов для IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Note
Можно также получить IFileProvider через PhysicalFileProvider. Такой подход может обеспечить бо́льшую гибкость в выборе расположения файлов правил перезаписи. Убедитесь, что файлы правил перезаписи развернуты на сервере по указанному вами пути.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Правило на основе метода
Используйте Add, чтобы реализовать собственную логику правил в методе.
Add открывает доступ к RewriteContext, который предоставляет HttpContext для использования в вашем методе.
RewriteContext.Result определяет, как осуществляется дополнительная обработка в конвейере. Установите значение одного из полей RuleResult из следующей таблицы.
| Результат перезаписи контекста | Action |
|---|---|
RuleResult.ContinueRules (по умолчанию) |
Продолжение применения правил. |
RuleResult.EndResponse |
Остановка применения правил и отправка отклика. |
RuleResult.SkipRemainingRules |
Прекратите применять правила и передайте контекст следующему промежуточному обработчику. |
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Приложение-пример демонстрирует способ, который перенаправляет запросы к путям, которые заканчиваются на .xml. Если запрос выполняется для /file.xml, запрос перенаправляется к /xmlfiles/file.xml. Код состояния получает значение 301 - Moved Permanently. Когда браузер отправляет новый запрос для /xmlfiles/file.xml, промежуточное ПО для статических файлов обслуживает файл клиенту из папки wwwroot/xmlfiles. Для перенаправления необходимо явно указать код состояния ответа. В противном случае возвращается код состояния 200 (ОК) и перенаправление на стороне клиента не происходит.
RewriteRules.cs:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Этот подход также переопределяет запросы. В примере приложения показано переопределение пути для любого запроса текстового файла, чтобы отправить текстовый файл file.txt из папки wwwroot. ПО промежуточного слоя статических файлов предоставляет файл по обновленному пути запроса:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Правило на основе IRule
Используйте Add, чтобы использовать собственную логику правил в классе, реализующем интерфейс IRule.
IRule позволяет более гибко применять правила, основанные на методах. Класс реализации может включать конструктор, который позволяет передавать параметры для метода ApplyRule.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Значения параметров в примере приложения для extension и newPath проверяются на соответствие нескольким условиям.
extension должен содержать одно из значений: .png, .jpg или .gif. Если newPath недопустим, вызывается исключение ArgumentException. Если запрос выполняется для image.png, запрос перенаправляется к /png-images/image.png. Если запрос выполняется для image.jpg, запрос перенаправляется к /jpg-images/image.jpg. Для кода состояния устанавливается значение 301 - Moved Permanently, а также задается значение context.Result, чтобы остановить обработку правил и отправить ответ.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Исходный запрос: /image.png
Исходный запрос: /image.jpg
Примеры регулярных выражений
| Goal | Пример строки регулярного выражения Пример сопоставления |
Строка замены & Пример вывода |
|---|---|---|
| Переопределение пути в строке запроса | ^path/(.*)/(.*)/path/abc/123 |
path?var1=$1&var2=$2/path?var1=abc&var2=123 |
| Удалить завершающий слеш | (.*)/$/path/ |
$1/path |
| Добавление косой черты в конце | (.*[^/])$/path |
$1//path/ |
| Избегайте переписывания конкретных запросов |
^(.*)(?<!\.axd)$ или ^(?!.*\.axd$)(.*)$Да: /resource.htmНет: /resource.axd |
rewritten/$1/rewritten/resource.htm/resource.axd |
| Переупорядочение сегментов URL-адреса | path/(.*)/(.*)/(.*)path/1/2/3 |
path/$3/$2/$1path/3/2/1 |
| Замена сегмента URL-адреса | ^(.*)/segment2/(.*)/segment1/segment2/segment3 |
$1/replaced/$2/segment1/replaced/segment3 |
Дополнительные ресурсы
- Просмотреть или скачать образец кода (описание загрузки)
-
RewriteMiddleware(эталонный источник) - Запуск приложения в ASP.NET Core
- Промежуточное ПО ASP.NET Core
- Регулярные выражения в .NET
- Элементы языка регулярных выражений — краткий справочник
- Apache mod_rewrite
- Использование модуля переопределения URL-адресов 2.0 (для IIS)
- Справочник по конфигурации модуля переопределения URL-адресов
- Сохранение простой структуры URL-адресов
- 10 советов по переопределению URL-адресов
- Ставить косую черту или нет
ASP.NET Core