Skip to content

Commit 42a9777

Browse files
committed
Use UriHelper.BuildAbsolute and UriHelper.BuildRelative for RedirectRule
1 parent e04dee0 commit 42a9777

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

src/Middleware/Rewrite/src/RedirectRule.cs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
using System;
55
using System.Text.RegularExpressions;
66
using Microsoft.AspNetCore.Http;
7-
using Microsoft.Net.Http.Headers;
7+
using Microsoft.AspNetCore.Http.Extensions;
88
using Microsoft.AspNetCore.Rewrite.Logging;
9+
using Microsoft.Net.Http.Headers;
910

1011
namespace Microsoft.AspNetCore.Rewrite
1112
{
@@ -34,13 +35,14 @@ public RedirectRule(string regex, string replacement, int statusCode)
3435

3536
public virtual void ApplyRule(RewriteContext context)
3637
{
37-
var path = context.HttpContext.Request.Path;
38-
var pathBase = context.HttpContext.Request.PathBase;
38+
var request = context.HttpContext.Request;
39+
var path = request.Path;
40+
var pathBase = request.PathBase;
3941

4042
Match initMatchResults;
41-
if (path == PathString.Empty)
43+
if (!path.HasValue)
4244
{
43-
initMatchResults = InitialMatch.Match(path.ToString());
45+
initMatchResults = InitialMatch.Match(string.Empty);
4446
}
4547
else
4648
{
@@ -56,31 +58,55 @@ public virtual void ApplyRule(RewriteContext context)
5658
response.StatusCode = StatusCode;
5759
context.Result = RuleResult.EndResponse;
5860

59-
if (string.IsNullOrEmpty(newPath))
60-
{
61-
response.Headers[HeaderNames.Location] = pathBase.HasValue ? pathBase.Value : "/";
62-
return;
63-
}
64-
65-
if (newPath.IndexOf(Uri.SchemeDelimiter, StringComparison.Ordinal) == -1 && newPath[0] != '/')
66-
{
67-
newPath = '/' + newPath;
68-
}
61+
string encodedPath;
6962

70-
var split = newPath.IndexOf('?');
71-
if (split >= 0)
63+
if (string.IsNullOrEmpty(newPath))
7264
{
73-
var query = context.HttpContext.Request.QueryString.Add(
74-
QueryString.FromUriComponent(
75-
newPath.Substring(split)));
76-
// not using the HttpContext.Response.redirect here because status codes may be 301, 302, 307, 308
77-
response.Headers[HeaderNames.Location] = pathBase + newPath.Substring(0, split) + query.ToUriComponent();
65+
encodedPath = pathBase.HasValue ? pathBase.Value : "/";
7866
}
7967
else
8068
{
81-
response.Headers[HeaderNames.Location] = pathBase + newPath + context.HttpContext.Request.QueryString.ToUriComponent();
69+
var host = default(HostString);
70+
var schemeSplit = newPath.IndexOf(Uri.SchemeDelimiter, StringComparison.Ordinal);
71+
if (schemeSplit >= 0)
72+
{
73+
schemeSplit += Uri.SchemeDelimiter.Length;
74+
var pathSplit = newPath.IndexOf('/', schemeSplit);
75+
76+
if (pathSplit == -1)
77+
{
78+
host = new HostString(newPath.Substring(schemeSplit));
79+
newPath = "/";
80+
}
81+
else
82+
{
83+
host = new HostString(newPath.Substring(schemeSplit, pathSplit - schemeSplit));
84+
newPath = newPath.Substring(pathSplit);
85+
}
86+
}
87+
88+
if (newPath[0] != '/')
89+
{
90+
newPath = '/' + newPath;
91+
}
92+
93+
var resolvedQuery = request.QueryString;
94+
var resolvedPath = newPath;
95+
var querySplit = newPath.IndexOf('?');
96+
if (querySplit >= 0)
97+
{
98+
resolvedQuery = request.QueryString.Add(QueryString.FromUriComponent(newPath.Substring(querySplit)));
99+
resolvedPath = newPath.Substring(0, querySplit);
100+
}
101+
102+
encodedPath = host.HasValue
103+
? UriHelper.BuildAbsolute(request.Scheme, host, pathBase, resolvedPath, resolvedQuery, default)
104+
: UriHelper.BuildRelative(pathBase, resolvedPath, resolvedQuery, default);
82105
}
83106

107+
// not using the HttpContext.Response.redirect here because status codes may be 301, 302, 307, 308
108+
response.Headers[HeaderNames.Location] = encodedPath;
109+
84110
context.Logger.RedirectedRequest(newPath);
85111
}
86112
}

src/Middleware/Rewrite/test/MiddlewareTests.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,19 @@ public async Task CheckRewritePath()
4545
Assert.Equal("http://example.com/foo", response);
4646
}
4747

48-
[Fact]
49-
public async Task CheckRedirectPath()
48+
[Theory]
49+
[InlineData("(.*)", "http://example.com/$1", null, "path", "http://example.com/path")]
50+
[InlineData("(.*)", "http://example.com", null, "", "http://example.com/")]
51+
[InlineData("(z*)", "$1", null, "path", "/")]
52+
[InlineData("(z*)", "http://example.com/$1", null, "path", "http://example.com/")]
53+
[InlineData("(z*)", "$1", "http://example.com/pathBase", "/pathBase/path", "/pathBase")]
54+
[InlineData("path/(.*)", "path?value=$1", null, "path/value", "/path?value=value")]
55+
[InlineData("path/(.*)", "path?param=$1", null, "path/value?param1=OtherValue", "/path?param1=OtherValue&param=value")]
56+
[InlineData("path/(.*)", "http://example.com/pathBase/path?param=$1", "http://example.com/pathBase", "path/value?param1=OtherValue", "http://example.com/pathBase/path?param1=OtherValue&param=value")]
57+
[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")]
58+
public async Task CheckRedirectPath(string pattern, string replacement, string baseAddress, string requestUrl, string expectedUrl)
5059
{
51-
var options = new RewriteOptions().AddRedirect("(.*)", "http://example.com/$1", statusCode: StatusCodes.Status301MovedPermanently);
60+
var options = new RewriteOptions().AddRedirect(pattern, replacement, statusCode: StatusCodes.Status301MovedPermanently);
5261
using var host = new HostBuilder()
5362
.ConfigureWebHost(webHostBuilder =>
5463
{
@@ -63,10 +72,14 @@ public async Task CheckRedirectPath()
6372
await host.StartAsync();
6473

6574
var server = host.GetTestServer();
75+
if (!string.IsNullOrEmpty(baseAddress))
76+
{
77+
server.BaseAddress = new Uri(baseAddress);
78+
}
6679

67-
var response = await server.CreateClient().GetAsync("foo");
80+
var response = await server.CreateClient().GetAsync(requestUrl);
6881

69-
Assert.Equal("http://example.com/foo", response.Headers.Location.OriginalString);
82+
Assert.Equal(expectedUrl, response.Headers.Location.OriginalString);
7083
}
7184

7285
[Fact]

0 commit comments

Comments
 (0)