Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Use UriHelper.BuildAbsolute for RedirectToHttpsRule #28899

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/Middleware/Rewrite/src/RedirectToHttpsRule.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Rewrite.Logging;
using Microsoft.Net.Http.Headers;

Expand All @@ -18,10 +18,11 @@ public virtual void ApplyRule(RewriteContext context)
if (!context.HttpContext.Request.IsHttps)
{
var host = context.HttpContext.Request.Host;
if (SSLPort.HasValue && SSLPort.Value > 0)
int port;
if (SSLPort.HasValue && (port = SSLPort.GetValueOrDefault()) > 0)
{
// a specific SSL port is specified
host = new HostString(host.Host, SSLPort.Value);
host = new HostString(host.Host, port);
}
else
{
Expand All @@ -30,10 +31,10 @@ public virtual void ApplyRule(RewriteContext context)
}

var req = context.HttpContext.Request;
var newUrl = new StringBuilder().Append("https://").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
var newUrl = UriHelper.BuildAbsolute("https", host, req.PathBase, req.Path, req.QueryString, default);
var response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = newUrl.ToString();
response.Headers[HeaderNames.Location] = newUrl;
context.Result = RuleResult.EndResponse;
context.Logger.RedirectedToHttps();
}
Expand Down
75 changes: 74 additions & 1 deletion src/Middleware/Rewrite/test/MiddlewareTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
Expand Down Expand Up @@ -128,7 +129,7 @@ public async Task CheckRedirectPathWithQueryString()
[InlineData(StatusCodes.Status302Found)]
[InlineData(StatusCodes.Status307TemporaryRedirect)]
[InlineData(StatusCodes.Status308PermanentRedirect)]
public async Task CheckRedirectToHttps(int statusCode)
public async Task CheckRedirectToHttpsStatus(int statusCode)
{
var options = new RewriteOptions().AddRedirectToHttps(statusCode: statusCode);
using var host = new HostBuilder()
Expand All @@ -152,6 +153,78 @@ public async Task CheckRedirectToHttps(int statusCode)
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);
}

[Fact]
public async Task CheckPermanentRedirectToHttps()
{
Expand Down