/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Middleware/Rewrite/test/MiddlewareTests.cs
1 091 строка
38 KB
Vlad
Fix CollapseLeadingSlashes bypass via bare leading backslash (#67928)
21 июл 2026, 14:50
Не верифицирован
21 июл 2026, 14:50
93148da
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules; public class MiddlewareTests { [Fact] public async Task CheckRewritePath() { var options = new RewriteOptions().AddRewrite("(.*)", "http://example.com/$1", skipRemainingRules: false); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/foo", response); } [Fact] public async Task CheckRewritePathWithSkipRemaining() { var options = new RewriteOptions().AddRewrite("(.*)", "http://example.com/$1", skipRemainingRules: true); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/foo", response); } [Fact] public async Task CheckRewritePath_MultipleRulesWithSkipRemaining() { var options = new RewriteOptions() .AddRewrite("(.*)", "http://example.com/$1", skipRemainingRules: true) .AddRewrite("(.*)", "http://example.com/42", skipRemainingRules: false); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/foo", response); } [Fact] public async Task CheckRewritePath_MultipleRules() { var options = new RewriteOptions() .AddRewrite("(.*)", "http://example.com/$1s", skipRemainingRules: false) .AddRewrite("(.*)", "http://example.com/$1/42", skipRemainingRules: false); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/foos/42", response); } [Theory] [InlineData("(.*)", "http://example.com/$1", null, "path", "http://example.com/path")] [InlineData("(.*)", "http://example.com", null, "", "http://example.com/")] [InlineData("(z*)", "$1", null, "path", "/")] [InlineData("(z*)", "http://example.com/$1", null, "path", "http://example.com/")] [InlineData("(z*)", "$1", "http://example.com/pathBase", "/pathBase/path", "/pathBase")] [InlineData("path/(.*)", "path?value=$1", null, "path/value", "/path?value=value")] [InlineData("path/(.*)", "path?param=$1", null, "path/value?param1=OtherValue", "/path?param1=OtherValue¶m=value")] [InlineData("path/(.*)", "http://example.com/pathBase/path?param=$1", "http://example.com/pathBase", "path/value?param1=OtherValue", "http://example.com/pathBase/path?param1=OtherValue¶m=value")] [InlineData("path/(.*)", "http://hoψst.com/pÂthBase/path?parãm=$1", "http://example.com/pathBase", "path/value?päram1=OtherValüe", "http://xn--host-cpd.com/p%C3%82thBase/path?p%C3%A4ram1=OtherVal%C3%BCe&parãm=value")] public async Task CheckRedirectPath(string pattern, string replacement, string baseAddress, string requestUrl, string expectedUrl) { var options = new RewriteOptions().AddRedirect(pattern, replacement, statusCode: StatusCodes.Status301MovedPermanently); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); if (!string.IsNullOrEmpty(baseAddress)) { server.BaseAddress = new Uri(baseAddress); } var response = await server.CreateClient().GetAsync(requestUrl); Assert.Equal(expectedUrl, response.Headers.Location.OriginalString); } [Theory] [InlineData("(.*)", "//example.com", "anything")] [InlineData("(.*)", "///example.com", "anything")] [InlineData("(.*)", @"/\example.com", "anything")] [InlineData("(.*)", "//////example.com", "anything")] [InlineData("legacy/(.*)", "/$1", "legacy//example.com")] [InlineData("legacy/(.*)", "/$1", "legacy///example.com")] [InlineData("legacy/(.*)", "/$1", @"legacy/\example.com")] [InlineData("(.*)", @"\example.com", "anything")] [InlineData("(.*)", @"\\example.com", "anything")] [InlineData("(.*)", @"\/\example.com", "anything")] [InlineData("legacy/(.*)", "/$1", @"legacy\\example.com")] public async Task CheckRedirect_CollapsesSchemeRelativeTarget(string pattern, string replacement, string requestUrl) { var options = new RewriteOptions().AddRedirect(pattern, replacement, statusCode: StatusCodes.Status302Found); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(requestUrl); Assert.Equal("/example.com", response.Headers.Location.OriginalString); } [Fact] public async Task RewriteRulesCanComeFromConfigureOptions() { using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .ConfigureServices(services => { services.Configure<RewriteOptions>(options => { options.AddRedirect("(.*)", "http://example.com/$1", statusCode: StatusCodes.Status301MovedPermanently); }); }) .Configure(app => { app.UseRewriter(); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync("foo"); Assert.Equal("http://example.com/foo", response.Headers.Location.OriginalString); } [Fact] public async Task CheckRedirectPathWithQueryString() { var options = new RewriteOptions().AddRedirect("(.*)", "http://example.com/$1", statusCode: StatusCodes.Status301MovedPermanently); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync("foo?bar=1"); Assert.Equal("http://example.com/foo?bar=1", response.Headers.Location.OriginalString); } [Theory] [InlineData(StatusCodes.Status301MovedPermanently)] [InlineData(StatusCodes.Status302Found)] [InlineData(StatusCodes.Status307TemporaryRedirect)] [InlineData(StatusCodes.Status308PermanentRedirect)] public async Task CheckRedirectToHttpsStatus(int statusCode) { var options = new RewriteOptions().AddRedirectToHttps(statusCode: statusCode); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("http://example.com")); Assert.Equal("https://example.com/", response.Headers.Location.OriginalString); Assert.Equal(statusCode, (int)response.StatusCode); } [Theory] [InlineData(null)] [InlineData(123)] public async Task CheckRedirectToHttpsSslPort(int? sslPort) { var options = new RewriteOptions().AddRedirectToHttps(statusCode: StatusCodes.Status302Found, sslPort: sslPort); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("http://example.com")); if (sslPort.HasValue) { Assert.Equal($"https://example.com:{sslPort.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)}/", response.Headers.Location.OriginalString); } else { Assert.Equal("https://example.com/", response.Headers.Location.OriginalString); } } [Theory] [InlineData(null, "example.com", "example.com/")] [InlineData(null, "example.com/path", "example.com/path")] [InlineData(null, "example.com/path?name=value", "example.com/path?name=value")] [InlineData(null, "hoψst.com", "xn--host-cpd.com/")] [InlineData(null, "hoψst.com/path", "xn--host-cpd.com/path")] [InlineData(null, "hoψst.com/path?name=value", "xn--host-cpd.com/path?name=value")] [InlineData(null, "example.com/pãth", "example.com/p%C3%A3th")] [InlineData(null, "example.com/path?näme=valüe", "example.com/path?n%C3%A4me=val%C3%BCe")] [InlineData("example.com/pathBase", "example.com/pathBase/path", "example.com/pathBase/path")] [InlineData("example.com/pathBase", "example.com/pathBase", "example.com/pathBase")] [InlineData("example.com/pâthBase", "example.com/pâthBase/path", "example.com/p%C3%A2thBase/path")] public async Task CheckRedirectToHttpsUrl(string baseAddress, string hostPathAndQuery, string expectedHostPathAndQuery) { var options = new RewriteOptions().AddRedirectToHttps(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); if (!string.IsNullOrEmpty(baseAddress)) { server.BaseAddress = new Uri("http://" + baseAddress); } var response = await server.CreateClient().GetAsync(new Uri("http://" + hostPathAndQuery)); Assert.Equal("https://" + expectedHostPathAndQuery, response.Headers.Location.OriginalString); } [Theory] [InlineData("http://example.com/test", "http://www.example.com/")] [InlineData("http://example.com/test", "https://www.example.com/")] [InlineData("https://example.com/test", "http://www.example.com/")] [InlineData("https://example.com/test", "https://www.example.com/")] public async Task CheckRedirectUsesConfiguredScheme(string hostSchemePathAndQuery, string redirectReplacement) { var options = new RewriteOptions().AddRedirect("test", redirectReplacement); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); server.BaseAddress = new Uri("http://example.com"); var response = await server.CreateClient().GetAsync(new Uri(hostSchemePathAndQuery)); // Regardless of whether we GET with http or https, the redirect should honor // the scheme specified in the configuration. Assert.Equal(redirectReplacement, response.Headers.Location.OriginalString); } [Fact] public async Task CheckPermanentRedirectToHttps() { var options = new RewriteOptions().AddRedirectToHttpsPermanent(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("http://example.com")); Assert.Equal("https://example.com/", response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status301MovedPermanently, (int)response.StatusCode); } [Theory] [InlineData(25, "https://example.com:25/")] [InlineData(-25, "https://example.com/")] public async Task CheckRedirectToHttpsWithSslPort(int sslPort, string expected) { var options = new RewriteOptions().AddRedirectToHttps(statusCode: StatusCodes.Status301MovedPermanently, sslPort: sslPort); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("http://example.com")); Assert.Equal(expected, response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status301MovedPermanently, (int)response.StatusCode); } [Theory] [InlineData(StatusCodes.Status301MovedPermanently)] [InlineData(StatusCodes.Status302Found)] [InlineData(StatusCodes.Status307TemporaryRedirect)] [InlineData(StatusCodes.Status308PermanentRedirect)] public async Task CheckRedirectToWwwWithStatusCode(int statusCode) { var options = new RewriteOptions().AddRedirectToWww(statusCode: statusCode); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("https://example.com")); Assert.Equal("https://www.example.com/", response.Headers.Location.OriginalString); Assert.Equal(statusCode, (int)response.StatusCode); } [Theory] [InlineData("http://example.com", "http://www.example.com/")] [InlineData("https://example.com", "https://www.example.com/")] [InlineData("http://example.com:8081", "http://www.example.com:8081/")] [InlineData("http://example.com:8081/example?q=1", "http://www.example.com:8081/example?q=1")] public async Task CheckRedirectToWww(string requestUri, string redirectUri) { var options = new RewriteOptions().AddRedirectToWww(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri(requestUri)); Assert.Equal(redirectUri, response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status307TemporaryRedirect, (int)response.StatusCode); } [Fact] public async Task CheckPermanentRedirectToWww() { var options = new RewriteOptions().AddRedirectToWwwPermanent(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("https://example.com")); Assert.Equal("https://www.example.com/", response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status308PermanentRedirect, (int)response.StatusCode); } [Theory] [InlineData("http://www.example.com")] [InlineData("https://www.example.com")] [InlineData("http://www.example.com:8081")] [InlineData("https://www.example.com:8081")] [InlineData("https://www.example.com:8081/example?q=1")] [InlineData("http://localhost")] [InlineData("https://localhost")] [InlineData("http://localhost:8081")] [InlineData("https://localhost:8081")] [InlineData("https://localhost:8081/example?q=1")] public async Task CheckNoRedirectToWww(string requestUri) { var options = new RewriteOptions().AddRedirectToWww(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri(requestUri)); Assert.Null(response.Headers.Location); } [Theory] [InlineData(StatusCodes.Status301MovedPermanently)] [InlineData(StatusCodes.Status302Found)] [InlineData(StatusCodes.Status307TemporaryRedirect)] [InlineData(StatusCodes.Status308PermanentRedirect)] public async Task CheckRedirectToNonWwwWithStatusCode(int statusCode) { var options = new RewriteOptions().AddRedirectToNonWww(statusCode: statusCode); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("https://www.example.com")); Assert.Equal("https://example.com/", response.Headers.Location.OriginalString); Assert.Equal(statusCode, (int)response.StatusCode); } [Theory] [InlineData("http://www.example.com", "http://example.com/")] [InlineData("https://www.example.com", "https://example.com/")] [InlineData("http://www.example.com:8081", "http://example.com:8081/")] [InlineData("http://www.example.com:8081/example?q=1", "http://example.com:8081/example?q=1")] public async Task CheckRedirectToNonWww(string requestUri, string redirectUri) { var options = new RewriteOptions().AddRedirectToNonWww(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri(requestUri)); Assert.Equal(redirectUri, response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status307TemporaryRedirect, (int)response.StatusCode); } [Fact] public async Task CheckPermanentRedirectToNonWww() { var options = new RewriteOptions().AddRedirectToNonWwwPermanent(); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("https://www.example.com")); Assert.Equal("https://example.com/", response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status308PermanentRedirect, (int)response.StatusCode); } [Fact] public async Task CheckIfEmptyStringRedirectCorrectly() { var options = new RewriteOptions().AddRedirect("(.*)", "$1", statusCode: StatusCodes.Status301MovedPermanently); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(""); Assert.Equal("/", response.Headers.Location.OriginalString); } [Fact] public async Task RewriteAfterUseRoutingHitsOriginalEndpoint() { // This is an edge case where users setup routing incorrectly, but we don't want to accidentally change behavior in case someone // relies on it, so we have this test var options = new RewriteOptions().AddRewrite("(.*)", "$1s", skipRemainingRules: false); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .ConfigureServices(s => { s.AddRouting(); }) .Configure(app => { app.UseRouting(); app.UseRewriter(options); app.UseEndpoints(endpoints => { endpoints.MapGet("/foos", context => context.Response.WriteAsync("bad")); endpoints.MapGet("/foo", context => context.Response.WriteAsync($"{context.GetEndpoint()?.DisplayName} from {context.Request.Path}")); }); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("HTTP: GET /foo from /foos", response); } [Fact] public async Task CheckIfEmptyStringRewriteCorrectly() { var options = new RewriteOptions().AddRewrite("(.*)", "$1", skipRemainingRules: false); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync( context.Request.Path + context.Request.QueryString)); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetStringAsync(""); Assert.Equal("/", response); } [Fact] public async Task SettingPathBase() { var options = new RewriteOptions().AddRedirect("(.*)", "$1"); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync( context.Request.Path + context.Request.QueryString)); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); server.BaseAddress = new Uri("http://localhost:5000/foo"); var response = await server.CreateClient().GetAsync(""); Assert.Equal("/foo", response.Headers.Location.OriginalString); } [Theory] [InlineData("http://example.com")] [InlineData("https://example.com")] [InlineData("http://example.com:8081")] [InlineData("https://example.com:8081")] [InlineData("https://example.com:8081/example?q=1")] public async Task CheckNoRedirectToWwwInNonWhitelistedDomains(string requestUri) { var options = new RewriteOptions().AddRedirectToWww("example2.com"); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri(requestUri)); Assert.Null(response.Headers.Location); } [Theory] [InlineData("http://example.com/", "http://www.example.com/")] [InlineData("https://example.com/", "https://www.example.com/")] [InlineData("http://example.com:8081", "http://www.example.com:8081/")] [InlineData("http://example.com:8081/example?q=1", "http://www.example.com:8081/example?q=1")] public async Task CheckRedirectToWwwInWhitelistedDomains(string requestUri, string redirectUri) { var options = new RewriteOptions().AddRedirectToWww("example.com"); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri(requestUri)); Assert.Equal(redirectUri, response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status307TemporaryRedirect, (int)response.StatusCode); } [Fact] public async Task CheckPermanentRedirectToWwwInWhitelistedDomains() { var options = new RewriteOptions().AddRedirectToWwwPermanent("example.com"); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("https://example.com")); Assert.Equal("https://www.example.com/", response.Headers.Location.OriginalString); Assert.Equal(StatusCodes.Status308PermanentRedirect, (int)response.StatusCode); } [Theory] [InlineData(StatusCodes.Status301MovedPermanently)] [InlineData(StatusCodes.Status302Found)] [InlineData(StatusCodes.Status307TemporaryRedirect)] [InlineData(StatusCodes.Status308PermanentRedirect)] public async Task CheckRedirectToWwwWithStatusCodeInWhitelistedDomains(int statusCode) { var options = new RewriteOptions().AddRedirectToWww(statusCode: statusCode, "example.com"); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); var response = await server.CreateClient().GetAsync(new Uri("https://example.com")); Assert.Equal("https://www.example.com/", response.Headers.Location.OriginalString); Assert.Equal(statusCode, (int)response.StatusCode); } [Theory] [InlineData("(.*)", "http://example.com/g")] [InlineData("/", "no rule")] public async Task Rewrite_WorksAfterUseRoutingIfGlobalRouteBuilderUsed(string regex, string output) { var options = new RewriteOptions().AddRewrite(regex, "http://example.com/g", skipRemainingRules: false); var builder = WebApplication.CreateBuilder(); builder.WebHost.UseTestServer(); await using var app = builder.Build(); app.UseRouting(); app.UseRewriter(options); app.UseEndpoints(endpoints => { endpoints.MapGet("/foo", context => context.Response.WriteAsync( "no rule")); endpoints.MapGet("/g", context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); await app.StartAsync(); var server = app.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal(output, response); } [Theory] [InlineData("(.*)", "http://example.com/g")] [InlineData("/", "no rule")] public async Task RewriteFromOptions_WorksAfterUseRoutingIfGlobalRouteBuilderUsed(string regex, string output) { var builder = WebApplication.CreateBuilder(); builder.WebHost.UseTestServer(); builder.Services.Configure<RewriteOptions>(options => { options.AddRewrite(regex, "http://example.com/g", skipRemainingRules: false); }); await using var app = builder.Build(); app.UseRouting(); app.UseRewriter(); app.UseEndpoints(endpoints => { endpoints.MapGet("/foo", context => context.Response.WriteAsync( "no rule")); endpoints.MapGet("/g", context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); await app.StartAsync(); var server = app.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal(output, response); } [Fact] public async Task RewriteSkipRemaing_WorksAfterUseRoutingIfGlobalRouteBuilderUsed() { var builder = WebApplication.CreateBuilder(); builder.WebHost.UseTestServer(); builder.Services.Configure<RewriteOptions>(options => { options.AddRewrite("(.*)", "http://example.com/g", skipRemainingRules: true); }); await using var app = builder.Build(); app.UseRouting(); app.UseRewriter(); app.UseEndpoints(endpoints => { endpoints.MapGet("/foo", context => context.Response.WriteAsync( "no rule")); endpoints.MapGet("/g", context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); await app.StartAsync(); var server = app.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/g", response); } [Fact] public async Task RewriteWithMultipleRules_WorksAfterUseRoutingIfGlobalRouteBuilderUsed() { var builder = WebApplication.CreateBuilder(); builder.WebHost.UseTestServer(); builder.Services.Configure<RewriteOptions>(options => { options.AddRewrite("(.*)", "http://example.com/g", skipRemainingRules: false) .AddRewrite("(.*)", "http://example.com/$1/h", skipRemainingRules: false); }); await using var app = builder.Build(); app.UseRouting(); app.UseRewriter(); app.UseEndpoints(endpoints => { endpoints.MapGet("/foo", context => context.Response.WriteAsync( "no rule")); endpoints.MapGet("/g/h", context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); await app.StartAsync(); var server = app.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/g/h", response); } [Fact] public async Task RewriteWithMultipleRulesAndSkip_WorksAfterUseRoutingIfGlobalRouteBuilderUsed() { var builder = WebApplication.CreateBuilder(); builder.WebHost.UseTestServer(); builder.Services.Configure<RewriteOptions>(options => { options.AddRewrite("(.*)", "http://example.com/g", skipRemainingRules: true) .AddRewrite("(.*)", "http://example.com/$1/h", skipRemainingRules: false); }); await using var app = builder.Build(); app.UseRouting(); app.UseRewriter(); app.UseEndpoints(endpoints => { endpoints.MapGet("/foo", context => context.Response.WriteAsync( "no rule")); endpoints.MapGet("/g", context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); }); await app.StartAsync(); var server = app.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/g", response); } [Fact] public async Task Rewrite_WorksWithoutUseRoutingWithWebApplication() { var builder = WebApplication.CreateBuilder(); builder.WebHost.UseTestServer(); builder.Services.Configure<RewriteOptions>(options => { options.AddRewrite("(.*)", "http://example.com/g", skipRemainingRules: true); }); await using var app = builder.Build(); app.UseRewriter(); app.MapGet("/foo", context => context.Response.WriteAsync( "no rule")); app.MapGet("/g", context => context.Response.WriteAsync( context.Request.Scheme + "://" + context.Request.Host + context.Request.Path + context.Request.QueryString)); await app.StartAsync(); var server = app.GetTestServer(); var response = await server.CreateClient().GetStringAsync("foo"); Assert.Equal("http://example.com/g", response); } }