1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Buffers ;
4
5
using System . Diagnostics ;
5
6
using System . Globalization ;
6
7
using Microsoft . AspNetCore . Http . Abstractions ;
@@ -15,6 +16,15 @@ namespace Microsoft.AspNetCore.Http;
15
16
[ DebuggerDisplay ( "{Value}" ) ]
16
17
public readonly struct HostString : IEquatable < HostString >
17
18
{
19
+ // Allowed Characters:
20
+ // A-Z, a-z, 0-9, .,
21
+ // -, %, [, ], :
22
+ // Above for IPV6
23
+ private static readonly SearchValues < char > s_safeHostStringChars =
24
+ SearchValues . Create ( "%-.0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz" ) ;
25
+
26
+ private static readonly IdnMapping s_idnMapping = new ( ) ;
27
+
18
28
private readonly string _value ;
19
29
20
30
/// <summary>
@@ -121,33 +131,23 @@ public override string ToString()
121
131
/// <returns>The <see cref="HostString"/> value formated for use in a URI or HTTP header.</returns>
122
132
public string ToUriComponent ( )
123
133
{
124
- if ( string . IsNullOrEmpty ( _value ) )
134
+ if ( ! HasValue )
125
135
{
126
136
return string . Empty ;
127
137
}
128
138
129
- int i ;
130
- for ( i = 0 ; i < _value . Length ; ++ i )
139
+ if ( ! _value . AsSpan ( ) . ContainsAnyExcept ( s_safeHostStringChars ) )
131
140
{
132
- if ( ! HostStringHelper . IsSafeHostStringChar ( _value [ i ] ) )
133
- {
134
- break ;
135
- }
141
+ return _value ;
136
142
}
137
143
138
- if ( i != _value . Length )
139
- {
140
- GetParts ( _value , out var host , out var port ) ;
141
-
142
- var mapping = new IdnMapping ( ) ;
143
- var encoded = mapping . GetAscii ( host . Buffer ! , host . Offset , host . Length ) ;
144
+ GetParts ( _value , out var host , out var port ) ;
144
145
145
- return StringSegment . IsNullOrEmpty ( port )
146
- ? encoded
147
- : string . Concat ( encoded , ":" , port . ToString ( ) ) ;
148
- }
146
+ var encoded = s_idnMapping . GetAscii ( host . Buffer ! , host . Offset , host . Length ) ;
149
147
150
- return _value ;
148
+ return StringSegment . IsNullOrEmpty ( port )
149
+ ? encoded
150
+ : string . Concat ( encoded , ":" , port . AsSpan ( ) ) ;
151
151
}
152
152
153
153
/// <summary>
@@ -177,14 +177,12 @@ public static HostString FromUriComponent(string uriComponent)
177
177
if ( index >= 0 )
178
178
{
179
179
// Has a port
180
- string port = uriComponent . Substring ( index ) ;
181
- var mapping = new IdnMapping ( ) ;
182
- uriComponent = mapping . GetUnicode ( uriComponent , 0 , index ) + port ;
180
+ var port = uriComponent . AsSpan ( index ) ;
181
+ uriComponent = string . Concat ( s_idnMapping . GetUnicode ( uriComponent , 0 , index ) , port ) ;
183
182
}
184
183
else
185
184
{
186
- var mapping = new IdnMapping ( ) ;
187
- uriComponent = mapping . GetUnicode ( uriComponent ) ;
185
+ uriComponent = s_idnMapping . GetUnicode ( uriComponent ) ;
188
186
}
189
187
}
190
188
}
0 commit comments