@@ -39,11 +39,7 @@ internal class GraphQLHttpWebSocket : IDisposable
3939 private Task _initializeWebSocketTask = Task . CompletedTask ;
4040 private readonly object _initializeLock = new object ( ) ;
4141
42- #if NETFRAMEWORK
43- private WebSocket _clientWebSocket = null ;
44- #else
45- private ClientWebSocket _clientWebSocket = null ;
46- #endif
42+ private WebSocket _clientWebSocket = null ;
4743
4844 #endregion
4945
@@ -83,6 +79,25 @@ public GraphQLHttpWebSocket(Uri webSocketUri, GraphQLHttpClient client)
8379 . Select ( request => Observable . FromAsync ( ( ) => SendWebSocketRequestAsync ( request ) ) )
8480 . Concat ( )
8581 . Subscribe ( ) ;
82+
83+ _connectedWebSocketFactory = async ( uri , token ) =>
84+ {
85+ #if NETFRAMEWORK
86+ var socket = InitializeNetClientWebSocket ( ) ;
87+ #else
88+ var socket = InitializeNetCoreClientWebSocket ( ) ;
89+ #endif
90+ Debug . WriteLine ( $ "opening websocket { socket . GetHashCode ( ) } (thread { Thread . CurrentThread . ManagedThreadId } )") ;
91+ await socket . ConnectAsync ( uri , token ) ;
92+ return socket ;
93+
94+ } ;
95+
96+ }
97+ internal GraphQLHttpWebSocket ( Uri webSocketUri , GraphQLHttpClient client , Func < Uri , CancellationToken , Task < WebSocket > > ? connectedWebSocketFactory ) : this ( webSocketUri , client )
98+ {
99+ if ( connectedWebSocketFactory != null )
100+ _connectedWebSocketFactory = connectedWebSocketFactory ;
86101 }
87102
88103 #region Send requests
@@ -379,71 +394,77 @@ public Task InitializeWebSocket()
379394
380395 // else (re-)create websocket and connect
381396 _clientWebSocket ? . Dispose ( ) ;
382-
397+ return _initializeWebSocketTask = ConnectAsync ( _internalCancellationToken ) ;
398+ }
399+ }
383400#if NETFRAMEWORK
384- // fix websocket not supported on win 7 using
385- // https://github.com/PingmanTools/System.Net.WebSockets.Client.Managed
386- _clientWebSocket = SystemClientWebSocket . CreateClientWebSocket ( ) ;
387- switch ( _clientWebSocket ) {
388- case ClientWebSocket nativeWebSocket :
389- nativeWebSocket . Options . AddSubProtocol ( "graphql-ws" ) ;
390- nativeWebSocket . Options . ClientCertificates = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . ClientCertificates ;
391- nativeWebSocket . Options . UseDefaultCredentials = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . UseDefaultCredentials ;
392- Options . ConfigureWebsocketOptions ( nativeWebSocket . Options ) ;
393- break ;
394- case System . Net . WebSockets . Managed . ClientWebSocket managedWebSocket :
395- managedWebSocket . Options . AddSubProtocol ( "graphql-ws" ) ;
396- managedWebSocket . Options . ClientCertificates = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . ClientCertificates ;
397- managedWebSocket . Options . UseDefaultCredentials = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . UseDefaultCredentials ;
398- break ;
399- default :
400- throw new NotSupportedException ( $ "unknown websocket type { _clientWebSocket . GetType ( ) . Name } ") ;
401- }
401+ private WebSocket InitializeNetClientWebSocket ( )
402+ {
403+ // fix websocket not supported on win 7 using
404+ // https://github.com/PingmanTools/System.Net.WebSockets.Client.Managed
405+ var socket = SystemClientWebSocket . CreateClientWebSocket ( ) ;
406+ switch ( socket ) {
407+ case ClientWebSocket nativeWebSocket :
408+ nativeWebSocket . Options . AddSubProtocol ( "graphql-ws" ) ;
409+ nativeWebSocket . Options . ClientCertificates = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . ClientCertificates ;
410+ nativeWebSocket . Options . UseDefaultCredentials = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . UseDefaultCredentials ;
411+ Options . ConfigureWebsocketOptions ( nativeWebSocket . Options ) ;
412+ break ;
413+ case System . Net . WebSockets . Managed . ClientWebSocket managedWebSocket :
414+ managedWebSocket . Options . AddSubProtocol ( "graphql-ws" ) ;
415+ managedWebSocket . Options . ClientCertificates = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . ClientCertificates ;
416+ managedWebSocket . Options . UseDefaultCredentials = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . UseDefaultCredentials ;
417+ break ;
418+ default :
419+ throw new NotSupportedException ( $ "unknown websocket type { socket . GetType ( ) . Name } ") ;
420+ }
421+ return socket ;
422+ }
402423#else
403- _clientWebSocket = new ClientWebSocket ( ) ;
404- _clientWebSocket . Options . AddSubProtocol ( "graphql-ws" ) ;
405-
406- // the following properties are not supported in Blazor WebAssembly and throw a PlatformNotSupportedException error when accessed
407- try
408- {
409- _clientWebSocket . Options . ClientCertificates = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . ClientCertificates ;
410- }
411- catch ( NotImplementedException )
412- {
413- Debug . WriteLine ( "property 'ClientWebSocketOptions.ClientCertificates' not implemented by current platform" ) ;
414- }
415- catch ( PlatformNotSupportedException )
416- {
417- Debug . WriteLine ( "property 'ClientWebSocketOptions.ClientCertificates' not supported by current platform" ) ;
418- }
424+ private ClientWebSocket InitializeNetCoreClientWebSocket ( )
425+ {
426+ var webSocket = new ClientWebSocket ( ) ;
427+ webSocket . Options . AddSubProtocol ( "graphql-ws" ) ;
419428
420- try
421- {
422- _clientWebSocket . Options . UseDefaultCredentials = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . UseDefaultCredentials ;
423- }
424- catch ( NotImplementedException )
425- {
426- Debug . WriteLine ( "property 'ClientWebSocketOptions.UseDefaultCredentials' not implemented by current platform" ) ;
427- }
428- catch ( PlatformNotSupportedException )
429- {
430- Debug . WriteLine ( "Property 'ClientWebSocketOptions.UseDefaultCredentials' not supported by current platform" ) ;
431- }
429+ // the following properties are not supported in Blazor WebAssembly and throw a PlatformNotSupportedException error when accessed
430+ try
431+ {
432+ webSocket . Options . ClientCertificates = ( ( HttpClientHandler ) Options . HttpMessageHandler ) . ClientCertificates ;
433+ }
434+ catch ( NotImplementedException )
435+ {
436+ Debug . WriteLine ( "property 'ClientWebSocketOptions.ClientCertificates' not implemented by current platform" ) ;
437+ }
438+ catch ( PlatformNotSupportedException )
439+ {
440+ Debug . WriteLine ( "property 'ClientWebSocketOptions.ClientCertificates' not supported by current platform" ) ;
441+ }
432442
433- Options . ConfigureWebsocketOptions ( _clientWebSocket . Options ) ;
434- #endif
435- return _initializeWebSocketTask = ConnectAsync ( _internalCancellationToken ) ;
443+ try
444+ {
445+ webSocket . Options . UseDefaultCredentials =
446+ ( ( HttpClientHandler ) Options . HttpMessageHandler ) . UseDefaultCredentials ;
447+ }
448+ catch ( NotImplementedException )
449+ {
450+ Debug . WriteLine ( "property 'ClientWebSocketOptions.UseDefaultCredentials' not implemented by current platform" ) ;
451+ }
452+ catch ( PlatformNotSupportedException )
453+ {
454+ Debug . WriteLine ( "Property 'ClientWebSocketOptions.UseDefaultCredentials' not supported by current platform" ) ;
436455 }
437- }
438456
457+ Options . ConfigureWebsocketOptions ( webSocket . Options ) ;
458+ return webSocket ;
459+ }
460+ #endif
439461 private async Task ConnectAsync ( CancellationToken token )
440462 {
441463 try
442464 {
443465 await BackOff ( ) ;
444466 _stateSubject . OnNext ( GraphQLWebsocketConnectionState . Connecting ) ;
445- Debug . WriteLine ( $ "opening websocket { _clientWebSocket . GetHashCode ( ) } (thread { Thread . CurrentThread . ManagedThreadId } )") ;
446- await _clientWebSocket . ConnectAsync ( _webSocketUri , token ) ;
467+ _clientWebSocket = await _connectedWebSocketFactory ( _webSocketUri , token ) ;
447468 _stateSubject . OnNext ( GraphQLWebsocketConnectionState . Connected ) ;
448469 Debug . WriteLine ( $ "connection established on websocket { _clientWebSocket . GetHashCode ( ) } , invoking Options.OnWebsocketConnected()") ;
449470 await ( Options . OnWebsocketConnected ? . Invoke ( _client ) ?? Task . CompletedTask ) ;
@@ -608,8 +629,6 @@ private async Task<WebsocketMessageWrapper> ReceiveWebsocketMessagesAsync()
608629 return response ;
609630
610631 case WebSocketMessageType . Close :
611- var closeResponse = await _client . JsonSerializer . DeserializeToWebsocketResponseWrapperAsync ( ms ) ;
612- closeResponse . MessageBytes = ms . ToArray ( ) ;
613632 Debug . WriteLine ( $ "Connection closed by the server.") ;
614633 throw new Exception ( "Connection closed by the server." ) ;
615634
@@ -670,6 +689,7 @@ public void Complete()
670689 public Task ? Completion { get ; private set ; }
671690
672691 private readonly object _completedLocker = new object ( ) ;
692+ private readonly Func < Uri , CancellationToken , Task < WebSocket > > _connectedWebSocketFactory ;
673693 private async Task CompleteAsync ( )
674694 {
675695 Debug . WriteLine ( "disposing GraphQLHttpWebSocket..." ) ;
0 commit comments