I read this question and this question . The former only explains 'no-cors' vs 'same-origin'; the latter recommends that 'no-cors' is not useful because of the Opaque Response (which Javascript cannot read/do anything useful with):
You basically never ever want to use mode: 'no-cors' in practice — except in some very limited cases. That’s because what setting mode: 'no-cors' actually says to the browser is, “Block my frontend JavaScript code from looking into the contents of the response body and headers under all circumstances.” In most cases that’s obviously really not what you want.
Can someone advise what are examples of these "limited cases" where we would want to use "no-cors" (even though the response is Opaque?)
The only case I can think of is a sort of one-way communication; if it is sufficient for the client to send a GET or POST to the server, simply so the server can track that the request happened; (for example, to increment a request counter); ...
...then it is sufficient for the response to be an OpaqueResponse; i.e. the client only need to know if the request was successful (status 200), doesn't expect any payload response.
Is my idea a valid example? Can someone recommend other possibilities / use-cases / examples of 'no-cors' usage?
no-cors. Prevents the method from being anything other than HEAD , GET or POST , and the headers from being anything other than simple headers. If any ServiceWorkers intercept these requests, they may not add or override any headers except for those that are simple headers.
An opaque response is for a request made for a resource on a different origin that doesn't return CORS headers. With an opaque response we won't be able to read the data returned or view the status of the request, meaning we can't check if the request was successful or not.
mode. The mode option is a safe-guard that prevents occasional cross-origin requests: "cors" – the default, cross-origin requests are allowed, as described in Fetch: Cross-Origin Requests, "same-origin" – cross-origin requests are forbidden, "no-cors" – only safe cross-origin requests are allowed.
Remember that CORS settings doesn't prevent a request from reaching the server - that's what authentication and CSRF is for. Instead, it prevents responses from being read by the page. The request is still:
Origin
header,Access-Control-Allow-Origin
. If it matches what the browser thinks is the Origin
then the browser lets the page see the result of the request.That's the key - Same-origin policy and CORS settings disallow the page in a cooperating browser from seeing the response.
Note also there is a step 0. above, which is an OPTIONS "pre-flight check" is sent to check that if the request was to go through would the page be allowed to see the result? If not, then they assume there is little point in sending the request - but that is an assumption.
mode: no-cors
does two things:
try { const notNeeded = fetch(...) } catch { console.log('Tough luck, do nothing') }
CORS does the above. It doesn't do the following:
The no-cors
mode limits the fetch API to operate like what is (and always has been) possible to with a form
element, plus some "small" extra capabilities — to perform a type of requests which the MDN documentation calls "simple". Additionally, just like with forms, the response is not accessible.
Forms (and all other HTML elements) can do cross-site requests without using the CORS protocol — their existence and behavior predates the CORS protocol.
The extra capabilities are those of simple requests which are beyond what HTML elements can achieve: using the HEAD
method, changing the value of simple headers, set/change parameters of simple content types, such as charset
.
I believe that the no-cors
mode exists to support the implementation of requests made by HTML elements. This statement from the MDN documentation for mode
seems to corroborate this idea:
However, for requests created other than by the Request() constructor,
no-cors
is typically used as themode
; for example, for embedded resources where the request is initiated from markup, unless thecrossorigin
attribute is present, the request is in most cases made using theno-cors
mode — that is, for the<link>
or<script>
elements (except when used with modules), or<img>
,<audio>
,<video>
,<object>
,<embed>
, or<iframe>
elements.
Apart from that, all cross-site use cases I can think of could instead use the cors
mode, offering more functionality (complex requests), without loss of safety.
A note regarding request simplicity/complexity. In the fetch/CORS specification the same request type concept is called CORS "safe", where safety refers to safe for old servers in the face of the new "unsafe" request types introduced by XHR/fetch. Simple requests themselves can, however, in no way be considered generally safe. In fact, it is these same request types which, when causing server-side persistent state mutations, must be protected against CSRF attacks! I guess this is why MDN rebaptized them as "simple" (yet generally unsafe!). For reference, the fetch/CORS specification mentions CORS-safety regarding methods, headers, the latter including the special Content-Type
header, among others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With