Dart Web Request and Response as a Stream of data

199 Views Asked by At

I have been trying to setup an HTTP connection from a Dart client to a Dart Server using the HttpServer and HttpClient classes respectively.

I want to use this connection to transmit event updates to the client whenever the server feels necessary, so the connection needs to be continuous and the response needs to be sent in chunks, not buffered.

I tried this approach using two different server configurations (once with HttpServer, once with Shelf), but both times the response awaited closing and then the data was printed by the client.

Here is my server code:

var httpsServer = await io.HttpServer.bind("127.0.0.1", 4001);
httpsServer.listen((request) {
    request.response.bufferOutput = false;
    request.response.headers.add("Content-Type", "text/event-stream");
    request.response.headers.add("Cache-Control", "no-cache");
    request.response.headers.add("Connection", "keep-alive");

    // asynchronously write "Hello" every 100 ms
    Timer.periodic(Duration(milliseconds: 100), (Timer timer) {
      try {
        request.response.write("Hello\n");
      } catch (_) {
        timer.cancel();
      }
    });
    await Future.delayed(Duration(seconds: 3));
    request.response.close();
});

And another using shelf:

{
    var handler = const Pipeline().addMiddleware(logRequests()).addHandler(_echoRequest);
    var server = await serve(handler, '127.0.0.1', 4000);
    server.autoCompress = true;
}

FutureOr<Response> _echoRequest(Request request) {
  Stream<List<int>> stream = Stream.periodic(Duration(milliseconds: 100), (int i) {
    return utf8.encode("Hello\n");
  }).take(10);
  return Response.ok(stream);
}

However, on the client, I only receive the data once the connection has been closed:

HttpClient client = HttpClient()..badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
  HttpClientRequest request = await client.postUrl(Uri.parse('https://---/'));
  request.headers.add('Content-Type', 'text/event-stream');
  HttpClientResponse response = await request.close();
  // use startChunkConversion to convert the stream of bytes to a stream of strings
  Stream<String> stream = response.transform(utf8.decoder).transform(const LineSplitter());
  await for (String line in stream) {
    print(line);
  }

Am I doing something wrong or would I be better off with a different library / approach?

0

There are 0 best solutions below