Lucas ARRIESSE
Rework JS + add settings btn
e4ce2a0
/**
* Performs a POST request and handles the response as a Server-Sent Events (SSE) stream.
* The standard EventSource API does not support POST requests, so we use fetch.
*
* @param {string} url The URL to send the POST request to.
* @param {object} body The JSON body for the POST request.
* @param {object} callbacks An object containing callback functions.
* @param {(data: object) => void} callbacks.onMessage A function called for each message received.
* @param {(error: Error) => void} callbacks.onError A function called if an error occurs.
*/
export async function postWithSSE(url, body, callbacks) {
const { onMessage, onError } = callbacks;
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'text/event-stream' // Politely ask for an event stream
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!response.body) {
throw new Error('Response body is null.');
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { value, done } = await reader.read();
// Decode the chunk of data and add it to our buffer.
// The `stream: true` option is important for multi-byte characters.
const chunk = decoder.decode(value, { stream: true });
buffer += chunk;
// SSE messages are separated by double newlines (`\n\n`).
// A single chunk from the stream might contain multiple messages or a partial message.
// We process all complete messages in the buffer.
let boundary;
while ((boundary = buffer.indexOf('\n\n')) !== -1) {
const messageString = buffer.substring(0, boundary);
buffer = buffer.substring(boundary + 2); // Remove the processed message from the buffer
// Skip empty keep-alive messages
if (messageString.trim() === '') {
continue;
}
// SSE "data:" lines. Your server only uses `data:`.
// We remove the "data: " prefix to get the JSON payload.
if (messageString.startsWith('data:')) {
const jsonData = messageString.substring('data: '.length);
try {
const parsedData = JSON.parse(jsonData);
if (parsedData.status === "complete")
return parsedData;
else
onMessage(parsedData);
} catch (e) {
console.error("Failed to parse JSON from SSE message:", jsonData, e);
// Optionally call the onError callback for parsing errors
if (onError) onError(new Error("Failed to parse JSON from SSE message."));
}
}
}
}
} catch (error) {
throw error;
}
}