Skip to content

Commit f28e12e

Browse files
authored
Use UriHelper.BuildAbsolute for RedirectToHttpsRule (#28899)
1 parent 2b493c4 commit f28e12e

File tree

2 files changed

+80
-6
lines changed

2 files changed

+80
-6
lines changed

src/Middleware/Rewrite/src/RedirectToHttpsRule.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System.Text;
54
using Microsoft.AspNetCore.Http;
5+
using Microsoft.AspNetCore.Http.Extensions;
66
using Microsoft.AspNetCore.Rewrite.Logging;
77
using Microsoft.Net.Http.Headers;
88

@@ -18,10 +18,11 @@ public virtual void ApplyRule(RewriteContext context)
1818
if (!context.HttpContext.Request.IsHttps)
1919
{
2020
var host = context.HttpContext.Request.Host;
21-
if (SSLPort.HasValue && SSLPort.Value > 0)
21+
int port;
22+
if (SSLPort.HasValue && (port = SSLPort.GetValueOrDefault()) > 0)
2223
{
2324
// a specific SSL port is specified
24-
host = new HostString(host.Host, SSLPort.Value);
25+
host = new HostString(host.Host, port);
2526
}
2627
else
2728
{
@@ -30,10 +31,10 @@ public virtual void ApplyRule(RewriteContext context)
3031
}
3132

3233
var req = context.HttpContext.Request;
33-
var newUrl = new StringBuilder().Append("https://").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
34+
var newUrl = UriHelper.BuildAbsolute("https", host, req.PathBase, req.Path, req.QueryString, default);
3435
var response = context.HttpContext.Response;
3536
response.StatusCode = StatusCode;
36-
response.Headers[HeaderNames.Location] = newUrl.ToString();
37+
response.Headers[HeaderNames.Location] = newUrl;
3738
context.Result = RuleResult.EndResponse;
3839
context.Logger.RedirectedToHttps();
3940
}

src/Middleware/Rewrite/test/MiddlewareTests.cs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Globalization;
56
using System.Threading.Tasks;
67
using Microsoft.AspNetCore.Builder;
78
using Microsoft.AspNetCore.Hosting;
@@ -128,7 +129,7 @@ public async Task CheckRedirectPathWithQueryString()
128129
[InlineData(StatusCodes.Status302Found)]
129130
[InlineData(StatusCodes.Status307TemporaryRedirect)]
130131
[InlineData(StatusCodes.Status308PermanentRedirect)]
131-
public async Task CheckRedirectToHttps(int statusCode)
132+
public async Task CheckRedirectToHttpsStatus(int statusCode)
132133
{
133134
var options = new RewriteOptions().AddRedirectToHttps(statusCode: statusCode);
134135
using var host = new HostBuilder()
@@ -152,6 +153,78 @@ public async Task CheckRedirectToHttps(int statusCode)
152153
Assert.Equal(statusCode, (int)response.StatusCode);
153154
}
154155

156+
[Theory]
157+
[InlineData(null)]
158+
[InlineData(123)]
159+
public async Task CheckRedirectToHttpsSslPort(int? sslPort)
160+
{
161+
var options = new RewriteOptions().AddRedirectToHttps(statusCode: StatusCodes.Status302Found, sslPort: sslPort);
162+
using var host = new HostBuilder()
163+
.ConfigureWebHost(webHostBuilder =>
164+
{
165+
webHostBuilder
166+
.UseTestServer()
167+
.Configure(app =>
168+
{
169+
app.UseRewriter(options);
170+
});
171+
}).Build();
172+
173+
await host.StartAsync();
174+
175+
var server = host.GetTestServer();
176+
177+
var response = await server.CreateClient().GetAsync(new Uri("http://example.com"));
178+
179+
if (sslPort.HasValue)
180+
{
181+
Assert.Equal($"https://example.com:{sslPort.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)}/", response.Headers.Location.OriginalString);
182+
}
183+
else
184+
{
185+
Assert.Equal("https://example.com/", response.Headers.Location.OriginalString);
186+
}
187+
}
188+
189+
[Theory]
190+
[InlineData(null, "example.com", "example.com/")]
191+
[InlineData(null, "example.com/path", "example.com/path")]
192+
[InlineData(null, "example.com/path?name=value", "example.com/path?name=value")]
193+
[InlineData(null, "hoψst.com", "xn--host-cpd.com/")]
194+
[InlineData(null, "hoψst.com/path", "xn--host-cpd.com/path")]
195+
[InlineData(null, "hoψst.com/path?name=value", "xn--host-cpd.com/path?name=value")]
196+
[InlineData(null, "example.com/pãth", "example.com/p%C3%A3th")]
197+
[InlineData(null, "example.com/path?näme=valüe", "example.com/path?n%C3%A4me=val%C3%BCe")]
198+
[InlineData("example.com/pathBase", "example.com/pathBase/path", "example.com/pathBase/path")]
199+
[InlineData("example.com/pathBase", "example.com/pathBase", "example.com/pathBase")]
200+
[InlineData("example.com/pâthBase", "example.com/pâthBase/path", "example.com/p%C3%A2thBase/path")]
201+
public async Task CheckRedirectToHttpsUrl(string baseAddress, string hostPathAndQuery, string expectedHostPathAndQuery)
202+
{
203+
var options = new RewriteOptions().AddRedirectToHttps();
204+
using var host = new HostBuilder()
205+
.ConfigureWebHost(webHostBuilder =>
206+
{
207+
webHostBuilder
208+
.UseTestServer()
209+
.Configure(app =>
210+
{
211+
app.UseRewriter(options);
212+
});
213+
}).Build();
214+
215+
await host.StartAsync();
216+
217+
var server = host.GetTestServer();
218+
if (!string.IsNullOrEmpty(baseAddress))
219+
{
220+
server.BaseAddress = new Uri("http://" + baseAddress);
221+
}
222+
223+
var response = await server.CreateClient().GetAsync(new Uri("http://" + hostPathAndQuery));
224+
225+
Assert.Equal("https://" + expectedHostPathAndQuery, response.Headers.Location.OriginalString);
226+
}
227+
155228
[Fact]
156229
public async Task CheckPermanentRedirectToHttps()
157230
{

0 commit comments

Comments
 (0)