Recently added cupertino web socket API uses web_socket package. However, there are some higher-level libraries like graphql, ferry or gql that still rely on dart:io WebSocket implementations via web_socket_channel package.
This means that the benefits coming from cupertino_http (like proxy support, observability via Xcode Instruments) cannot be leveraged there without additional work.
I'd like to request an adapter example that could let us use CupertinoWebSocket with web_socket_channel. It could be just a part of the documentation on how to use cupertino_http with dart:io-related packages.
In my first attempt I tried to wrap CupertinoWebSocket with WebSocketChannel via StreamChannelMixin. It doesn't work but feels like relatively acceptable amount of code to be put into the documentation (assuming it works).
Is such addition to the docs possible?
Edit: I found AdapterWebSocketChannel class that can be used as follows:
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:async/async.dart' as async;
import 'package:cupertino_http/cupertino_http.dart';
import 'package:http/http.dart';
import 'package:stream_channel/stream_channel.dart' as sc;
import 'package:web_socket/web_socket.dart' as ws;
import 'package:web_socket_channel/web_socket_channel.dart' as wsc;
// usage
return AdapterWebSocketChannel(
CupertinoWebSocket.connect(
Uri.parse(baseWs),
protocols: ['graphql-transport-ws'],
config: URLSessionConfiguration.defaultSessionConfiguration(),
),
);
// adapter below
class AdapterWebSocketChannel extends sc.StreamChannelMixin implements wsc.WebSocketChannel {
// ...
AdapterWebSocketChannel(FutureOr<ws.WebSocket> webSocket) {
// ...
}
Previous non working impl
import 'dart:io';
import 'dart:typed_data';
import 'package:cupertino_http/cupertino_http.dart';
import 'package:stream_channel/stream_channel.dart' as sc;
import 'package:web_socket/web_socket.dart' as ws;
import 'package:web_socket_channel/web_socket_channel.dart' as wsc;
class CupertinoWebSocketChannelAdapter {
static Future<wsc.WebSocketChannel> connect(String baseWs) async {
final socket = await CupertinoWebSocket.connect(
Uri.parse(baseWs),
protocols: ['graphql-transport-ws'],
config: URLSessionConfiguration.defaultSessionConfiguration(),
);
socket.events.asBroadcastStream().listen((e) async {
switch (e) {
case ws.TextDataReceived(text: final text):
print('Received Text: $text');
case ws.BinaryDataReceived(data: final data):
print('Received Binary: $data');
case ws.CloseReceived(code: final code, reason: final reason):
print('Connection to server closed: $code [$reason]');
}
});
return wsc.WebSocketChannel(StreamChannelAdapter(socket));
}
}
class StreamChannelAdapter with sc.StreamChannelMixin<List<int>> {
StreamChannelAdapter(this._socket) {
// subscription not handled
print('AdapterStreamChannel created');
_sinkController.stream.listen(
(event) {
print('AdapterStreamChannel event: $event');
final bytes = Uint8List.fromList(event);
_socket.sendBytes(bytes);
},
onDone: () => {
print('AdapterStreamChannel done'),
},
);
}
final StreamController<List<int>> _sinkController = StreamController<List<int>>.broadcast();
final CupertinoWebSocket _socket;
@override
StreamSink<List<int>> get sink => _sinkController.sink;
@override
Stream<List<int>> get stream => _socket.events.asBroadcastStream().map((e) {
print('AdapterStreamChannel event: $e');
switch (e) {
case ws.TextDataReceived(text: final text):
return text.codeUnits;
case ws.BinaryDataReceived(data: final data):
return data;
case ws.CloseReceived(code: final code, reason: final reason):
throw Exception('Connection to server closed: $code [$reason]');
}
});
}
Related
Recently added cupertino web socket API uses
web_socketpackage. However, there are some higher-level libraries like graphql, ferry or gql that still rely ondart:ioWebSocketimplementations viaweb_socket_channelpackage.This means that the benefits coming from cupertino_http (like proxy support, observability via Xcode Instruments) cannot be leveraged there without additional work.
I'd like to request an adapter example that could let us use
CupertinoWebSocketwithweb_socket_channel. It could be just a part of the documentation on how to usecupertino_httpwithdart:io-related packages.In my first attempt I tried to wrap CupertinoWebSocket with WebSocketChannel via StreamChannelMixin. It doesn't work but feels like relatively acceptable amount of code to be put into the documentation (assuming it works).
Is such addition to the docs possible?
Edit: I found AdapterWebSocketChannel class that can be used as follows:
Previous non working impl
Related