websocketstreamingfastapi

Flutter only reads FastAPI StreamingResponse at the end of the stream


Overview

I'm currently experimenting on a Stream functionality so I can later integrate it with a software i'm building. I'm trying to stream information from my backend built with FastAPI, to my frontend, built with Flutter. I have a GET endpoint in my backend to which I request the stream data from my frontend application. The endpoint integration in itself is working well, so the issues are regarding the implementation of the stream functionality.

If there is any information that I have not provided here but may be needed to better understand the problem, please don't hesitate in asking me to provide it. This feature is really important to me, and I would love to get it working :)

I'll explain below the issue i'm encountering.

Problem

From what I researched in the Internet, using the FastAPI StreamResponse will let me send packets of information to a stream that'll be read by the frontend of my application, from a GET request to the endpoint.

The backend correctly sends the information in intervals through the StreamResponse, but my frontend seems to freeze until all the information has arrived, and I have closed the stream.

FastAPI Backend Endpoint

The backend code I wrote to send information via Stream.

async def fake_streamer():
    for _ in range(10):
        print("Sending frame")
        yield b"Hey!"
        time.sleep(1)
    
@app.get("/camera/{camera_id}")
def read_camera(camera_id: int):
    return StreamingResponse(fake_streamer())

Flutter Frontend Request

Code that makes the request to the backend endpoint. This function is called when I click on an ElevatedButton, for simplicity.

void fetchData() async {
    final url = Uri.parse('http://127.0.0.1:8001/camera/30');
    final client = http.Client();

    try {
      final request = http.Request('GET', url);
      final response = await client.send(request);
      await for (var data in response.stream.transform(utf8.decoder)) {
        print(data);
      }
    } catch (e) {
      print(e);
    } finally {
      client.close();
    }
  }

Video demonstration

On the left is my backend console logs, and in the right my Flutter logs. Screen print was taken while transmitting the information via Stream.

On the left is my backend console logs, and in the right my Flutter logs. Screen print was taken  while transmitting the information via Stream.

On the left is my backend console logs, and in the right my Flutter logs. Screen print was taken at the end of transmitting the information via Stream, and closing it.

On the left is my backend console logs, and in the right my Flutter logs. Screen print was taken at the end of transmitting the information via Stream, and closing it.

Approaches tried

I tried two different approaches to this feature, and both had the same result (Flutter receiving all packets at the end of transmission, or websocket connection close):

Resources read:

Update #1

Tried a workaround from a suggestion that I was awaiting for the whole stream to resolve. Behaviour remains unchanged.

...
      final request = http.Request('GET', url);
      final response = await client.send(request);
      response.stream.listen((var data){
        print(data);
      });
...

Solution

  • That's probably happening because you used await on the for loop, which waits for the response.stream to resolve (which occurs when the stream finishes).

    Use the await with the data instead. E.g.:

    print((await data))
    

    Also add code snippets directly instead of adding screenshots of the code