blob: 1edbd6f3b688eb887e9808a91d9655de580601f7 [file] [log] [blame]
// Copyright 2024 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
import 'dart:async';
import 'package:stream_channel/stream_channel.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
/// A record of a [StreamChannel] and a [Stream] of logs of protocol traffic
/// in both directions across it.
typedef LoggedChannel = ({StreamChannel<String> channel, Stream<String> log});
/// Connects to the websocket at [wsUri] and returns a channel along with
/// a log stream that includes all protocol traffic.
Future<LoggedChannel> createLoggedWebSocketChannel(Uri wsUri) async {
final logController = StreamController<String>();
final rawChannel = WebSocketChannel.connect(wsUri);
await rawChannel.ready;
final rawStringChannel = rawChannel.cast<String>();
/// A helper to create a function that can be used in stream.map() to log
/// traffic with a prefix.
String Function(String) logTraffic(String prefix) {
return (String s) {
logController.add('$prefix $s'.trim());
return s;
};
}
// Create a channel that logs the data going through it.
final loggedInput = rawStringChannel.stream.map(logTraffic('==>'));
final loggedOutputController = StreamController<String>();
unawaited(
loggedOutputController.stream
.map(logTraffic('<=='))
.pipe(rawStringChannel.sink),
);
return (
channel: StreamChannel<String>(loggedInput, loggedOutputController.sink),
log: logController.stream,
);
}