11using System . Buffers ;
2+ using System . Collections . Immutable ;
23using System . IO . Pipelines ;
34using System . Net . Security ;
45using System . Net . Sockets ;
@@ -31,12 +32,12 @@ public sealed class RawWebsocketConnection : IAsyncDisposable
3132 private readonly string _host ;
3233 private readonly int _port ;
3334 private readonly bool _isDefaultPort ;
34- private readonly string _route ;
35+ private readonly ReadOnlyMemory < byte > _route ;
3536
3637 private readonly int _rxMaxBufferSize ;
3738 private readonly int _txMaxBufferSize ;
3839
39- private const string Crlf = "\r \n " ;
40+ private readonly ReadOnlyMemory < byte > _clrf = "\r \n "u8 . ToArray ( ) ;
4041
4142 #region Get-/Setters
4243
@@ -95,51 +96,46 @@ public async Task TryUpgrade(IRequest request, CancellationToken token = default
9596 throw new InvalidOperationException ( "Not initialized." ) ;
9697 }
9798
98- // todo: make this more effient with readonly memory instead of a string?
99-
100- var upgradeRequestSb = new StringBuilder ( ) ;
101-
102- upgradeRequestSb
103- // GET {_route} HTTP/1.1\r\n
104- . Append ( "GET " )
105- . Append ( _route )
106- . Append ( " HTTP/1.1" )
107- . Append ( Crlf )
108- // Host: {_host}:{_port}\r\n
109- . Append ( "Host: " )
110- . Append ( _host ) ;
99+ var writer = new ArrayBufferWriter < byte > ( ) ;
111100
101+ writer . Write ( "GET "u8 ) ;
102+ writer . Write ( _route . Span ) ;
103+ writer . Write ( " HTTP/1.1"u8 ) ;
104+ writer . Write ( _clrf . Span ) ;
105+
106+ writer . Write ( "Host: "u8 ) ;
107+ writer . Write ( Encoding . ASCII . GetBytes ( _host ) ) ;
108+
112109 if ( ! _isDefaultPort )
113110 {
114- upgradeRequestSb . Append ( ':' ) ;
115- upgradeRequestSb . Append ( _port ) ;
111+ writer . Write ( ":"u8 ) ;
112+ writer . Write ( Encoding . ASCII . GetBytes ( _port . ToString ( ) ) ) ;
116113 }
117114
118- upgradeRequestSb . Append ( Crlf ) ;
115+ writer . Write ( _clrf . Span ) ;
119116
120117 var headers = request . Header . Headers ;
121118
122119 for ( var i = 0 ; i < headers . Count ; i ++ )
123120 {
124121 var header = headers [ i ] ;
125122
126- var key = header . Key . ToString ( ) ;
127- var value = header . Value . ToString ( ) ;
123+ var key = header . Key ;
124+ var value = header . Value ;
128125
129- if ( key . Equals ( "Host" , StringComparison . OrdinalIgnoreCase ) )
126+ if ( key == KnownHeaders . Host )
130127 continue ;
131128
132- upgradeRequestSb
133- . Append ( key )
134- . Append ( ": " )
135- . Append ( value )
136- . Append ( Crlf ) ;
129+ writer . Write ( key . Bytes . Span ) ;
130+ writer . Write ( ":"u8 ) ;
131+ writer . Write ( value . Bytes . Span ) ;
132+ writer . Write ( _clrf . Span ) ;
137133 }
138134
139- upgradeRequestSb . Append ( Crlf ) ;
135+ writer . Write ( _clrf . Span ) ;
140136
141137 // Writes and flushes
142- await Pipe . Output . WriteAsync ( Encoding . UTF8 . GetBytes ( upgradeRequestSb . ToString ( ) ) , token ) ;
138+ await Pipe . Output . WriteAsync ( writer . WrittenMemory , token ) ;
143139
144140 // Read the handshake response until \r\n\r\n
145141 while ( request . Server . Running )
@@ -179,10 +175,12 @@ public async Task TryUpgrade(IRequest request, CancellationToken token = default
179175 }
180176 }
181177
182- private static ( string host , int port , bool isDefaultPort , bool secure , string route ) GetHostPortAndSecurity ( string url )
178+ private static ( string host , int port , bool isDefaultPort , bool secure , ReadOnlyMemory < byte > route ) GetHostPortAndSecurity ( string url )
183179 {
184180 if ( ! Uri . TryCreate ( url , UriKind . Absolute , out var uri ) )
181+ {
185182 throw new ArgumentException ( $ "Invalid URL: { url } ", nameof ( url ) ) ;
183+ }
186184
187185 var secure = uri . Scheme . Equals ( "https" , StringComparison . OrdinalIgnoreCase ) ||
188186 uri . Scheme . Equals ( "wss" , StringComparison . OrdinalIgnoreCase ) ;
@@ -200,7 +198,7 @@ private static (string host, int port, bool isDefaultPort, bool secure, string r
200198
201199 var route = string . IsNullOrEmpty ( uri . PathAndQuery ) ? "/" : uri . PathAndQuery ;
202200
203- return ( uri . Host , port , uri . IsDefaultPort , secure , route ) ;
201+ return ( uri . Host , port , uri . IsDefaultPort , secure , Encoding . ASCII . GetBytes ( route ) ) ;
204202 }
205203
206204 public async ValueTask DisposeAsync ( )
0 commit comments