4
4
using System ;
5
5
using System . Text . RegularExpressions ;
6
6
using Microsoft . AspNetCore . Http ;
7
- using Microsoft . Net . Http . Headers ;
7
+ using Microsoft . AspNetCore . Http . Extensions ;
8
8
using Microsoft . AspNetCore . Rewrite . Logging ;
9
+ using Microsoft . Net . Http . Headers ;
9
10
10
11
namespace Microsoft . AspNetCore . Rewrite
11
12
{
@@ -34,13 +35,14 @@ public RedirectRule(string regex, string replacement, int statusCode)
34
35
35
36
public virtual void ApplyRule ( RewriteContext context )
36
37
{
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 ;
39
41
40
42
Match initMatchResults ;
41
- if ( path == PathString . Empty )
43
+ if ( ! path . HasValue )
42
44
{
43
- initMatchResults = InitialMatch . Match ( path . ToString ( ) ) ;
45
+ initMatchResults = InitialMatch . Match ( string . Empty ) ;
44
46
}
45
47
else
46
48
{
@@ -56,31 +58,55 @@ public virtual void ApplyRule(RewriteContext context)
56
58
response . StatusCode = StatusCode ;
57
59
context . Result = RuleResult . EndResponse ;
58
60
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 ;
69
62
70
- var split = newPath . IndexOf ( '?' ) ;
71
- if ( split >= 0 )
63
+ if ( string . IsNullOrEmpty ( newPath ) )
72
64
{
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 : "/" ;
78
66
}
79
67
else
80
68
{
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 ) ;
82
105
}
83
106
107
+ // not using the HttpContext.Response.redirect here because status codes may be 301, 302, 307, 308
108
+ response . Headers [ HeaderNames . Location ] = encodedPath ;
109
+
84
110
context . Logger . RedirectedRequest ( newPath ) ;
85
111
}
86
112
}
0 commit comments