@@ -11,6 +11,9 @@ namespace Microsoft.AspNetCore.Http.Extensions
11
11
/// </summary>
12
12
public static class UriHelper
13
13
{
14
+ private const string ForwardSlash = "/" ;
15
+ private const string Pound = "#" ;
16
+ private const string QuestionMark = "?" ;
14
17
private const string SchemeDelimiter = "://" ;
15
18
16
19
/// <summary>
@@ -70,6 +73,91 @@ public static string BuildAbsolute(
70
73
. ToString ( ) ;
71
74
}
72
75
76
+ /// <summary>
77
+ /// Seperates the given absolute URI string into components. Assumes no PathBase.
78
+ /// </summary>
79
+ /// <param name="uri">A string representation of the uri.</param>
80
+ /// <param name="scheme">http, https, etc.</param>
81
+ /// <param name="host">The host portion of the uri normally included in the Host header. This may include the port.</param>
82
+ /// <param name="path">The portion of the request path that identifies the requested resource.</param>
83
+ /// <param name="query">The query, if any.</param>
84
+ /// <param name="fragment">The fragment, if any.</param>
85
+ public static void FromAbsolute (
86
+ string uri ,
87
+ out string scheme ,
88
+ out HostString host ,
89
+ out PathString path ,
90
+ out QueryString query ,
91
+ out FragmentString fragment )
92
+ {
93
+ if ( uri == null )
94
+ {
95
+ throw new ArgumentNullException ( nameof ( uri ) ) ;
96
+ }
97
+
98
+ // Satisfy the out parameters
99
+ path = new PathString ( ) ;
100
+ query = new QueryString ( ) ;
101
+ fragment = new FragmentString ( ) ;
102
+
103
+ var schemeIndex = uri . IndexOf ( SchemeDelimiter ) ;
104
+ if ( schemeIndex < 0 )
105
+ {
106
+ throw new FormatException ( "No scheme delimiter in uri." ) ;
107
+ }
108
+
109
+ scheme = uri . Substring ( 0 , schemeIndex ) ;
110
+
111
+ // PERF: Calculate the end of the scheme for next IndexOf
112
+ schemeIndex += SchemeDelimiter . Length ;
113
+
114
+ // TODO Discuss URI without path/pathbase but with query/fragment
115
+ var hostIndex = uri . IndexOf ( ForwardSlash , schemeIndex ) ;
116
+
117
+ if ( hostIndex < 0 )
118
+ {
119
+ // Ex: http://example.com
120
+ host = new HostString ( uri . Substring ( schemeIndex ) ) ;
121
+ return ;
122
+ }
123
+
124
+ // if trailing slash (http://example.com/, PathString will be created with slash, which is fine.
125
+ host = new HostString ( uri . Substring ( schemeIndex , hostIndex - schemeIndex ) ) ;
126
+
127
+ var pathIndex = uri . IndexOf ( QuestionMark , hostIndex ) ;
128
+
129
+ if ( pathIndex < 0 )
130
+ {
131
+ // Means there is no query, look for fragment.
132
+ pathIndex = uri . IndexOf ( Pound , hostIndex ) ;
133
+ if ( pathIndex < 0 )
134
+ {
135
+ // no fragment, create PathString out of rest of uri
136
+ path = new PathString ( uri . Substring ( hostIndex ) ) ;
137
+ }
138
+ else
139
+ {
140
+ // make new PathString and FragmentString at found index
141
+ path = new PathString ( uri . Substring ( hostIndex , pathIndex - hostIndex ) ) ;
142
+ fragment = new FragmentString ( uri . Substring ( pathIndex ) ) ;
143
+ }
144
+ return ;
145
+ }
146
+
147
+ path = new PathString ( uri . Substring ( hostIndex , pathIndex - hostIndex ) ) ;
148
+
149
+ var queryIndex = uri . IndexOf ( Pound , pathIndex ) ;
150
+ if ( queryIndex < 0 )
151
+ {
152
+ // no fragment, create QueryString out of rest of uri
153
+ query = new QueryString ( uri . Substring ( pathIndex ) ) ;
154
+ return ;
155
+ }
156
+ // make new QueryString and FragmentString at found index
157
+ query = new QueryString ( uri . Substring ( pathIndex , queryIndex - pathIndex ) ) ;
158
+ fragment = new FragmentString ( uri . Substring ( queryIndex ) ) ;
159
+ }
160
+
73
161
/// <summary>
74
162
/// Generates a string from the given absolute or relative Uri that is appropriately encoded for use in
75
163
/// HTTP headers. Note that a unicode host name will be encoded as punycode.
0 commit comments