Monday, 5 November, 2018 UTC


Summary

In this article, we explain what Cross-Origin Resource Sharing (CORS) is and how to avoid errors associated with it and the Access-Control-Allow-Origin header. This includes describing it both from the viewpoint of the frontend and the backend.
CORS: Cross-Origin Resource Sharing
Cross-Origin Resource Sharing (CORS) is a mechanism allowing (or disallowing) the resources to be requested from another origin than it is served on. It is built into the browsers and uses HTTP headers to determine whether or not it is safe to allow a cross-origin request. When a web application requests a source with a different origin (origin includes a domain, a protocol, and a port) it is cross-origin. Browsers restrict such requests unless the response from the other origin includes the right headers.
Let’s jump straight into coding. We use a simple Express app here:
const express = require('express');

const app = express();

app.get('/posts', function(req, res) {
  res.send([
    {
      id: 0,
      title: 'Lorem ipsum',
      content: 'Dolor sit amet',
      author: 'Marcin'
    },
    {
      id: 1,
      title: 'Vestibulum cursus',
      content: 'Dante ut sapien mattis',
      author: 'Marcin'
    }
  ]);
});

app.listen(8080);
This, when running locally, opens the
http://localhost:8080/posts
 endpoint.
So far so good. Now try to use Postman to perform a GET request.
A success! Let’s modify our app a little and add an additional endpoint:
app.get('/', function(req, res) {
  res.send();
});
This will give us an empty document at the 
http://localhost:8080
 address. Let’s open it in the browser, and in DevTools execute:
fetch('http://localhost:8080/posts');
Works fine as well!
In this example, we run our request in the same origin, but this is often not the case. Imagine creating a frontend app that runs in a different origin, for example on a different port. To create such a situation, let’s run an additional express app on a different port.
const express = require('express');

const app = express();

app.get('/', function(req, res) {
  res.send();
});

app.listen(4200);
Now, let’s open our second app at the address
http://localhost:4200
 and try to perform the same fetch request.
This results in an error:
Access to fetch at ‘http://localhost:8080/posts’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
As you can see, the request itself was successful, but the browser blocked it.

Conclusions

  • The first example includes us using Postman, so the CORS mechanism wasn’t involved
  • In the second example, we perform a request from the same origin, so the CORS mechanism didn’t block our request
  • The third example is a Cross-Origin request and therefore it is blocked.
    This does not need to be the case. As the error states, we can set the Access-Control-Allow-Origin header. You need to attach it to the response that the browser receives from the server.
Access-Control-Allow-Origin header
To specify what origins have access to the resource, you need to add the Access-Control-Allow-Origin header to your response. It will be interpreted by the browser of the visitor of your site.
While using Express there are a few ways to do that. The simplest one is to attach the header straight in the handler:
app.get('/posts', function(req, res) {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
  res.send([
    {
      id: 0,
      title: 'Lorem ipsum',
      content: 'Dolor sit amet',
      author: 'Marcin'
    },
    {
      id: 1,
      title: 'Vestibulum cursus',
      content: 'Dante ut sapien mattis',
      author: 'Marcin'
    }
  ]);
});
This will tell the browser that it is safe to request a resource from that origin.
It works! But that means that you would have to call 
setHeader
 in the every one of your handlers. This is where you can use middleware:
app.use(function (req, res, next) {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
  next();
});
If you call the 
use
 function, the callback you provide will be executed every time a request is sent to the server. It results in attaching the Access-Control-Allow-Origin header to all your responses.

Possible values

One of the possibilities is to specify an exact origin as we did in the previous example. If you choose to be specific, you need to all the way: browsers do not support multiple Access-Control-Allow-Origin headers. On the other hand, you can use a wildcard:
res.setHeader('Access-Control-Allow-Origin', '*');
This value tells the browser that the given resource can be shared with any origin. There is one catch though: when using a wildcard, you can’t send or receive cookies. If you try to do so, the browser throws an error.
Other ways to bypass the CORS policy
One way to override the CORS policy is to install an extension such as Allow-Control-Allow-Origin: *. It Adds the 
Allow-Control-Allow-Origin: *
  header to the all the responses that your browser receives. As mentioned above, it disrupts the way that cookies are sent and received, so keep that in mind.
Another thing you can do is to specify in your request, that you want to bypass the CORS secure mechanism. You can do it if you use Fetch API by setting  the mode parameter to no-cors:
fetch('http://localhost:8080/posts', { mode: 'no-cors' });
This will work regardless of the Access-Control-Allow-Origin header. There is no equivalent of that in the XMLHttpRequest, unfortunately.
If you would like to know more about Fetch API and XMLHttpRequest, check out Comparing working with JSON using the XHR and the Fetch API
Summary
In this article, we explained what the Cross-Origin Resource Sharing (CORS) is, and how can we deal with it in terms of the origin access control. It included creating a simple backend express app and sending requests both from Postman and the browser to illustrate how the CORS works. Aside from that, the article provided tips on how to deal with this error by setting the Access-Control-Allow-Origin header, using browser extensions and an additional parameter that you can set in the Fetch API request. This can help you design both your frontend and backend while keeping the CORS mechanism in mind.
The post Cross-Origin Resource Sharing. Avoiding Access-Control-Allow-Origin CORS error appeared first on Marcin Wanago Blog - JavaScript, both frontend and backend.