fetch-event-source icon indicating copy to clipboard operation
fetch-event-source copied to clipboard

handle basic request errors or update README with a demonstration

Open iambumblehead opened this issue 4 years ago • 5 comments
trafficstars

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 :)

iambumblehead avatar Jul 08 '21 21:07 iambumblehead

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 avatar Feb 11 '22 02:02 eli-darkly

@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 avatar Feb 11 '22 18:02 iambumblehead

@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.

eli-darkly avatar Feb 11 '22 20:02 eli-darkly

Unfortunately it seems like it's not actively maintained these days.

eli-darkly avatar Feb 11 '22 20:02 eli-darkly

@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.

RSMuthu avatar May 11 '22 06:05 RSMuthu