My server emits a Server-side Event of json data. Now during the 'loading' period, the payload is short, but when the stream is completed I get a Format exception because the payload exceeds the content-length of the chunk.
Is there a way to ensure that the chunk is a full string before the
final imageEventProvider = StreamProvider.autoDispose<Map<String, dynamic>>(
(ref) async* {
final request = http.Request(
'POST',
backendUrl().replace(
pathSegments: ['gen-image'],
),
);
final auth = ref.read(authProvider);
request.body = jsonEncode({'prompt': 'a desert landscape'});
request.headers["Accept"] = "text/event-stream";
request.headers["Cache-Control"] = "no-cache";
request.headers['Content-Type'] = 'application/json';
request.headers['X-FIREBASE-TOKEN'] = await auth.currentUser!.getIdToken();
final sResp = await request.send();
final predictionStream = sResp.stream.transform(utf8.decoder);
await for (final part in predictionStream) {
final Map<String, dynamic> data = jsonDecode(part);
if (data['status'] != 'succeeded') {
ref.state = const AsyncLoading();
}
yield data;
}
},
);
I want to make sure the chuck is full string before passing it off to jsonDecode. Would that be possible?
Edit
Server Side
The model for the event in the python server:
@dataclass
class SSEvent:
message: dict[str, Any]
def encode(self) -> bytes:
return json.dumps(self.message).encode("utf-8")
And how the response is structured.
async def sse():
pred_resp = await client.post(
url,
json={"version": version, "input": input},
headers=headers,
)
data = pred_resp.json()
pred_url = "{}/{}".format(url, data["id"])
while data["status"] != "succeeded":
pred_resp = await client.post(pred_url, headers=headers)
data = pred_resp.json()
event = SSEvent({"status": "loading"})
yield event.encode()
else:
data = pred_resp.json()
event = SSEvent(
{
**data,
}
)
yield event.encode()
response = await make_response(
sse(),
{
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Transfer-Encoding": "chunked",
},
)
Client side
As per suggestions by @pskink I have changed the provider. But the FormatExceptions persists
final imageEventProvider = StreamProvider.autoDispose<Map<String, dynamic>>(
(ref) async* {
final request = http.Request(
'POST',
backendUrl().replace(
pathSegments: ['gen-image'],
),
);
final auth = ref.read(authProvider);
request.body = jsonEncode({'prompt': 'a desert landscape'});
request.headers["Accept"] = "text/event-stream";
request.headers["Cache-Control"] = "no-cache";
request.headers['Content-Type'] = 'application/json';
request.headers['X-FIREBASE-TOKEN'] = await auth.currentUser!.getIdToken();
final sResp = await request.send();
final predictionStream = sResp.stream.transform(json.fuse(utf8).decoder);
final data = await predictionStream.single as Map<String, dynamic>;
if (data!['status'] != 'succeeded') {
ref.state = AsyncLoading();
}
yield data;
},
);
I still get a FormatException.