By default, the Fetch algorithm uses 'no-cors' as the mode for requests. However, in certain situations specified in the spec, a different mode such as 'cors' is used for cross-origin requests.
For cross-origin requests specifically, the Fetch algorithm sets the response tainting to 'cors' and requires the use of the CORS protocol for fetching.
The Main fetch algorithm's step 12 contains substeps that determine the mode based on various conditions.
↪ The request's current URL origin matches the request's origin and CORS flag is unset
↪ Request's current URL scheme is "data
"
↪ Request's mode is "navigate
" or "websocket
"
- Set request's response tainting to "
basic
".
- Return the result of performing a scheme fetch using the request.
…
↪ The request's mode is "no-cors
"
- Set request's response tainting to "
opaque
".
- Return the result of performing a scheme fetch using the request.
…
↪ Otherwise
- Set request's response tainting to "
cors
".
- Return the result of performing an HTTP fetch using request with CORS flag set.
In summary, if the request URL doesn't match your code's origin, the scheme isn't data
, and the mode isn't explicitly set to navigate
, websocket
, or no-cors
, then the request is made using the CORS protocol.
There is a notable difference between setting the mode to 'no-cors' and leaving it unspecified.
Setting mode to 'no-cors' makes the response inaccessible to JavaScript.
This occurs because the specific substep for 'no-cors' mode is executed instead of the generic one.
Not specifying a mode allows the Response object to be accessible.
This happens when the generic substep is reached, triggering a CORS-enabled fetch.
Is there a difference in behavior between specifying the fetch mode and letting it use the default mode?
Yes, explicitly setting the mode to 'no-cors' for a cross-origin request bypasses CORS, while not specifying the mode results in a CORS-enabled fetch.
The statement about the mode defaulting to 'no-cors' unless otherwise specified does not imply that all requests made with fetch()
have their mode locked to 'no-cors'.