corsfetchgeneral-network-error

Distinguish network error from opaque response in fetch with 'no-cors'


tldr; How are opaque responses distinguishable from a network error when sending a fetch request with mode: 'no-cors'?

I believe:

Can anyone confirm? (Edit: Same approach as used here)


Background: From my UI I want to check if various urls are reachable (e.g. that they are not blocked by firewall). In this answer: https://stackoverflow.com/a/53442328/1534823 it says:

no-cors mode means that if the browser has to do anything that requires permission from CORS, it will fail silently instead of throwing an error.

Question:

If a fetch request with 'no-cors' header:

Documentation:

Pro: In chrome dev-tools I can simulate network errors by blocking domains, which seems to indicate the above 2 statements are true - but I am not sure how reliably that reflects real-life network errors.

Contra: These docs fail to mention that CORS exceptions also throw a TypeError for the fetch: https://developer.mozilla.org/en-US/docs/Web/API/fetch#exceptions

Contra: In the fetch spec: https://fetch.spec.whatwg.org/#concept-filtered-response-opaque it says:

In other words, an opaque filtered response and an opaque-redirect filtered response are nearly indistinguishable from a network error.

... or can I use the CORS preflight request somehow to check if a server which disallows CORS is reachable? (or just send an OPTIONS request?)


Solution

  • There are many questions here.

    You are correct that an opaque response does not result in rejection of the promise. However, a CORS failure results in a network error, not an opaque response. However, you cannot get a CORS failure if you use "no-cors" (note that this is not a header, it's an input to a Request object).

    With "no-cors" you are restricted in the HTTP methods you can use, so OPTIONS is not an option (no joke). Browsers are also increasingly putting limits on what "no-cors" can reach as these responses are problematic in a world with Spectre. https://github.com/annevk/orb has more details on this. So long term using fetch(url, { mode: "no-cors" }) will probably not get you what you want as you will increasingly see more network errors, despite the server potentially being reachable.