fetch-event-source
fetch-event-source copied to clipboard
handle basic request errors or update README with a demonstration
an error is seen in the browser tools using the below call TypeError: Error in body stream
await new fetchEventSource( `${endpointUrl}/path-does-not-exist`, {
onerror ( err ) {
console.log( 'error', err );
},
onclose ( ev ) {
console.log( 'close', ev );
}
});
How does one get error details, such as a response code 404, 401 or 400? Thank you :)
It looks to me like fetchEventSource does not check the response status before proceeding, so if there's a 4xx response— which presumably does not have SSE content in the response body— it will try to read the response body as a stream anyway, causing an error as described.
I think with the current implementation, the way an application can handle this is to provide an onopen handler like this:
onopen: resp => {
if (resp.status != 200) {
throw new Error(`error status ${resp.status}`);
}
}
Any exception thrown from onopen will be handled the same as if fetch had thrown the exception, so you will then get it in onerror. You could use a custom type instead of Error to distinguish HTTP status errors from other errors.
However, I agree that it'd be desirable for fetchEventSource to have some default error-handling behavior of its own for this, since the SSE specification does say that all status other than 200 and 3xx should be treated as errors.
@eli-darkly thanks for the reply. I'll try your suggestion the next time I work with these scripts, which may not be soon
@iambumblehead, to be clear, that's just my guess based on reading the code. I haven't tried using fetch-event-source yet except in very simple ways— I've just started looking into adopting it in our code.
Unfortunately it seems like it's not actively maintained these days.
@iambumblehead I feel its designed to be that way. The developer needs to have flexibility on handling how the response needs to be. Here is a sample on how I handle it on my end,
onopen (res) {
const contentType = res.headers.get('content-type');
if (!contentType?.startsWith('text/event-stream')) {
throw new FatalError(`Expected content-type to be text/event-stream, Actual: ${contentType}`);
}
if (res.ok && res.status === 200) {
return
}
if (res.status >= 400 && res.status < 500 && res.status !== 429) {
throw new FatalError()
}
// Anything other than above cases are retried
throw new RetriableError()
}
}
onerror (err) {
if (err instanceof FatalError) {
throw err; // rethrow to stop the operation
} else {
// In this case, we are going to retry
}
}
This should help you with basic response handling. You may use this as sample and extend it for your specific usecase.