Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of request.mode in the fetch API, especially with respect to cors?

Looking at the new fetch API, you can specificy a mode field in the request. From Mozilla:

The mode read-only property of the Request interface contains the mode 
of the request (e.g., cors, no-cors, same-origin, or navigate.) This is 
used to determine if cross-origin requests lead to valid responses, and 
which properties of the response are readable.

And then how to use it:

var myHeaders = new Headers();

var myInit = { method: 'GET',
           headers: myHeaders,
           mode: 'cors',
           cache: 'default' };

fetch('flowers.jpg', myInit).then(function(response) {
  return response.blob();
}).then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

I don't understand why would you would need to specificy something that is so self evident in the request itself? If I was requesting a resource from http://foo.com servers on the client website http://client.com, doesn't the server have the origin header to look at? And wouldn't the mode only cause confusion?

Furthermore I'm trying to figure out what goal mode: same-origin would even serve? "You could use this to ensure that a request is always being made to your origin." But if you're sending a request out, or if another developer has access to the code, why wouldn't you just not send the request instead of a field to indicate it's invalid?

like image 473
Afs35mm Avatar asked Oct 29 '22 22:10

Afs35mm


2 Answers

It has nothing to do with the server; the server will get the request, regardless. This is true of Fetch and of XMLHttpRequest. If your server is naive and does something dumb, regardless of who is passing it what, from where, that's its own fault, and this has nothing to do with preventing that.

It has to do with what the client will let you see of the response, and what gets sent to the server (in terms of credentials via headers, in conjunction with the credentials field).

Consider a server that doesn't do CORS headers, but just blindly assumes that you are at the same origin, and returns JSON... ...now, assume that Fetch allows you to request resources across origins (it does).

The mode dictates that if this kind of request is made, and this kind of response is given, that the payload should be completely opaque to the receiver of the Fetch request... which means that you can get a response, just like you always could, but you can't actually get the body to parse it or use it.

This is a big deal, in terms of both allowing you to be able to make requests across origins, as well as keeping the browser safer.

It even has practical applications, such as preloading/prefetching data that, perhaps, some host API is going to use (like <img> or <video>), where those interfaces are given more authority to access foreign data than the sandbox your JS runs in.

These same sorts of concepts also apply to ServiceWorkers and caching opaque blobs for origins that are decidedly not your origin (caching and serving Gravatar images at the service-worker level, for example).

like image 75
Norguard Avatar answered Nov 15 '22 06:11

Norguard


The Fetch API by design exposes the same primitives that browsers use for fetches internally.

mode is one of those primitives. And it’s not just used in the part of the Fetch spec that defines the Fetch API — because the Fetch spec, along with defining that JavaScript API, also defines low-level algorithms for how browsers handle fetches of various kinds internally.

Browser-internal algorithms defined in specs such as the HTML spec reference those low-level algorithms in the Fetch spec, and rely on setting the mode and other aspects of the fetch.

For example, in the HTML spec, the fetch a classic worker script algorithm starts with this:

To fetch a classic worker script given a url, a fetch client settings object, a destination, and a script settings object, run these steps. The algorithm will asynchronously complete with either null (on failure) or a new classic script (on success).

  1. Let request be a new request whose url is url, client is fetch client settings object, destination is destination, mode is "same-origin", credentials mode is "same-origin", parser metadata is "not parser-inserted", and whose use-URL-credentials flag is set.

Note the «Let request be a new request» and «mode is "same-origin parts — and notice that the hyperlink for request goes to https://fetch.spec.whatwg.org/#concept-request and the hyperlink for mode goes to https://fetch.spec.whatwg.org/#concept-request-mode.

So the HTML spec has need for the "same-origin" mode setting for requests — in order to specify behavior that browsers use internally when making a certain type of fetch.

And that kind of thing is why the Fetch spec needs to provide for fetches to have particular modes. Along with that, the reason the Fetch API provides the ability to set the "same-origin" mode is (as mentioned above) in keeping with the goal of allowing you as a web developer to have access to the same primitives browsers have access to internally when making fetches.

You may not ever find need for all the various modes the Fetch API exposes — it’s pretty unlikely you’d ever want to use the navigate mode — but they’re all there nonetheless, because they represent the complete set of modes that are needed for any given fetch scenario (including scenarios that are only ever likely to be used by browsers internally).

like image 40
5 revs Avatar answered Nov 15 '22 06:11

5 revs