Understanding Cors

For Solving Common Errors

Understanding Cors

INTRODUCTION

Most of us have heard the term CORS from an error message, popping up while doing a network request. Before getting into solving this error let's understand what does CORS exactly mean and check whether it's really bad as you think.

In the olden days of the web, we were only allowed to share resources between the same origin, here origin can be considered as a single domain or a server. This was fine until microservice architecture became widely adopted and there was a need for the browser to communicate to different domains. This is where CORS come into the picture.

cors1.png

CORS

It is an HTTP-header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources. CORS also relies on a mechanism by which browsers make a “preflight” request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.

There are two types of cross-origin requests:

  1. Safe requests.
  2. All the others.

Safe Requests are simpler to make, so let’s start with them.

A request is safe if it satisfies two conditions:

  1. Safe method: GET, POST or HEAD
  2. Safe headers – the only allowed custom headers are:

    • Accept,

    • Accept-Language,

    • Content-Language,

    • Content-Type with the value application/x-www-form-urlencoded, multipart/form-data or text/plain.

Any other request is considered “unsafe”. For instance, a request with a PUT method or with an API-Key HTTP header does not fit the limitations

Handling CORS Errors

The reason for you to get a CORS error is that your request does not come under the safe request category, one way of fixing this error would be adding a proxy server, this makes use of the property that CORS restrictions are not there in server to server communications. If you are working on a react app build using create-react-app, the react-scripts provide you with a proxy server, but this is only for development purposes so it's not a proper solution.

If you have control over the API then the best solution would be to add the CORS headers before sending the response to your request.

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null

The above headers can be used to allow some or all certain origins to access the server resources. Similarly, there are more headers that you can add to allow different content-Types, methods etc. You can learn more about the different headers here.

Hopefully, you are now able to understand what caused this error and a possible fix, now let's try to implement this solution using code, I am going to use express js for this particular demo.

The following code shows a simple express app

const express = require('express');

const app = express();

app.use(express.json());

app.listen(3000, () => {
  console.log(`listening on port 3000`)
})

// routes
app.get('/', (req, res) => res.render('home'));
app.put('/books',  (req, res) => {
  books = updatebook() // some function to update books
  res.send("books updated")
});

Then the browser is requesting for the /books resource from another origin there will be a CORS error as we are not attaching any CORS header to the response hence the preflight request will fail to raise the CORS Error. Now let's see how to add a simple express middleware that can add this necessary header to the responses.

const express = require('express');

const app = express();

app.use(express.json());

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers','*');
  next();
});

app.listen(3000, () => {
  console.log(`listening on port 3000`)
})

// routes
app.get('/', (req, res) => res.render('home'));
app.put('/books',  (req, res) => {
  books = updatebook() // some function to update books
  res.send("books updated")
});

app. use applied this middleware to all requests in our server, you can read more about express middleware here.

So from the next request, our server adds 'Access-Control-Allow-Origin' and 'Access-Control-Allow-Headers' to our requests so this will allow the browser to accept the resources from our server and CORS error will not be there. Note that the headers you need to include are the ones needed according to your question, do refer to the link I shared before for reading more about the other headers available

Before wrapping up I would like to add one more thing, that is about the different modes available in browsers fetch API, it is just a way to control how the browser should attempt to cross-origin requests and will not help in accessing cors restricted resources.

The different mode options available are the following:

  • "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. This option may be useful when the URL for fetch comes from a 3rd-party, and we want a “power off switch” to limit cross-origin capabilities.