Magnus
Magnus

Reputation: 18790

How to receive server-sent events (SSE) in Flutter Web?

I have tried several different SSE-plugins to receive server-sent events in a Flutter Web app, and all of them can connect but I don't receive any events in Flutter. However, if I open DevTools in Chrome and go to Network -> EventStream, I see the events coming in from the server. What could be the reason I don't receive them in the app?

I have tried sse, sse_client and eventsource, but the result is the same in all of them.

Here's how I implemented the app using the sse_client plugin:

sseClient = SseClient.connect(Uri.parse('https://example.com/test-sse/index.php'));
print('sse connected');

sseClient.stream.listen(
    (event) {
      print('sse event: ${event.toString()}');
  },
  onError: (err){
    print('sse error');
  },
  onDone: (){
    print('sse closed');
  },
);

The only output I get is sse connected, and then nothing - even though the events keep coming in the DevTools Network/EventStream tab.

Here's my PHP test script:

<?php

ob_end_clean();

set_time_limit(60);

while (true) {
    // Headers must be processed line by line.
    header('Access-Control-Allow-Origin: http://localhost:56008');
    header('Access-Control-Allow-Credentials: true');
    header('Content-Type: text/event-stream; charset=utf-8');
    header('Cache-Control: no-cache');

    $data = [
        'message' => 'Event: server-time='.date('G:H:s', time()),
        'dummy' => str_repeat(' ',1024*64)
    ];
    print("id: ".microtime()."\n");
    print("event: ping\n");
    print('data: '.json_encode($data)."\n");
    print("\n");

    ob_flush();
    flush();
    
    sleep(1);
}

I have tried removing the id and the dummy etc., but the result is the same - the browser receives the events, but the app doesn't receive anything.

Upvotes: 4

Views: 5663

Answers (1)

Timo B&#228;hr
Timo B&#228;hr

Reputation: 2051

Use fetch_client at web until this open Flutter issue is resolved.

sse_stream.dart: Get stream on Android/iOS/Mac/Windows:

import 'package:http/http.dart';

Future<ByteStream> getStream(Request request) async {
  final client = Client();
  StreamedResponse response = await client.send(request);
  return response.stream;
}

sse_stream_web.dart: Get stream on web:

import 'package:fetch_client/fetch_client.dart';
import 'package:http/http.dart';

Future<ByteStream> getStream(Request request) async {
  final FetchClient fetchClient = FetchClient(mode: RequestMode.cors);
  final FetchResponse response = await fetchClient.send(request);
  return response.stream;
}

Conditional import:

import 'path/to/sse_stream.dart' if (dart.library.js) 'path/to/sse_client_web.dart';

Upvotes: 4

Related Questions