React & REST API: How to overcome CORS errors
Tags: react, javascript, node, tutorial
Published: 2021-03-15 08:01:53

---
published: true
title: React & REST API: How to overcome CORS errors
description: Learn how to set up an Express server to proxy your React App's REST API requests
series: React & REST API
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x6w46f0tfpcw0dqbm62.png
tags: react, javascript, node, tutorial
---

In Part 2 of this series, we'll be making a REST API call from our React project to a service that has some CORS policies implemented. In this particular example, we'll make REST API calls to xkcd's API.

# <u>Make REST API calls to xkcd</u>

## What is xkcd?

xkcd is a webcomic series created by American author Randall Munroe. You can find the awesome comics [here](https://xkcd.com/).

## xkcd has an API?

Yes, it does indeed have an API.
You can find the great and concise API docs [here](https://xkcd.com/json.html).

## What are we going to do?

We'll make REST API calls to one of my favorite comic strips that has an ID of 327, i.e. our endpoint will be `https://xkcd.com/327/info.0.json`. This will return JSON data about that particular comic strip.

## Let's try calling it!

OK, so the implementation should be fairly simple. We made our REST API call to the Random User Generator API in our previous article - we just have to switch around the endpoint URL, right?

```javascript
//const restEndpoint = "https://randomuser.me/api/";
const restEndpoint = "https://xkcd.com/327/info.0.json";
```

OK that was super easy! Now let's refresh our React page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v7o8oqv1yenok6myux5.png)

...? *Access to fetch at blah blah from origin bleh bleh has been blocked by CORS policy* .... say what now???

Well, it looks like the response didn't render. And there seems to be a whole lot of red text in the console...\_(┐「ε:)\_

That error we see in the console is well known as the **CORS Error**. Basically, resources that lie on xkcd's domain cannot be requested from another domain (i.e. our front-end React App).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vfible4z27nqlxxcqhs3.jpg)

There are several ways we can overcome this issue:
1. Make REST API calls from the same domain as xkcd
2. Edit the CORS settings of xkcd's server
3. Make REST API calls from our own backend server

We can quickly experience method 1 if we navigate to any page on xkcd, and run the following code in the console.

```javascript
fetch('https://xkcd.com/327/info.0.json')
  .then(response => response.json())
  .then(data => console.log(data));
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwrle8cpj0wmv5071eaf.png)

The REST API request is being made on the same domain, so we don't run into any CORS errors. But it's highly unlikely that xkcd will host our React App on their site for us, so this isn't a realistic approach.

Method 2 again is unrealistic, since we don't have permission to access the settings of xkcd's server ¯\\_(ツ)_/¯

Method 3 is achievable by either setting up your own server and making requests from it, or using a services such as Zapier or Power Automate to make the requests for us.

In this article, we'll proceed with Method 3 by setting up a backend server using Express, which will act as a proxy to make REST API calls to xkcd.

# <u>Set up Express</u>

## What is Express?

[Express](https://expressjs.com/) is a back-end web application framework for Node.

## How will we use Express?

In this article, we'll treat Express as a tool for creating custom endpoints that our front-end React App can make calls to. When we make requests to these custom endpoints, the *Express server* will make REST API calls to our desired 3rd party service endpoint, receive the response, and then route the response back to our React App.

If that was a bit hard to grasp, think of it like ordering food at a nice restaurant. If **we (front-end App)** go directly to the kitchen and order food directly to the **chef (3rd party service)**, we'll be scolded for **bad manners (CORS errors)**. What we need to do is order food to the **server (Express App)**. The **server (Express App)** will take our order, walk to the kitchen, and request for the food to the **chef (3rd party service)**. After some time, the **chef (3rd party service)** will respond by giving the **server (Express App)** back a plate of food. The **server (Express App)** then carries the plate back to the table so that **we (front-end App)** can consume it.

## Set up Express

OK, so let's go ahead to set up Express. This is basically a new node project with the Express dependencies installed. We'll want this project to be in a separate location from our React App, so let's navigate back up to our **myproject** directory, create a new directory called **backend**, and navigate into it. Since the terminal we were using is running the React app, go ahead to use the commands in a new terminal window.

```
mkdir backend
cd backend
```

From here we'll follow the [Express installation tutorial](https://expressjs.com/en/starter/installing.html) to make our Express project.

```
npm init
```

You'll be asked a number of questions but you can skip through them by hitting enter until it's finished.

Continue to install some dependencies.

```
npm install express node-fetch cors
```

Finally, create a JavaScript file to work on - we'll call ours **server.js**.

```
touch server.js
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3aglh3f729yp06uh8972.png)

## Set up the Express code

We'll use this code for **server.js**

```javascript
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');

const PORT = 5000;
const app = express();

app.use(cors());
const corsOptions = {
    origin: "http://localhost:3000"
};

const requestEndpoint = "https://xkcd.com/327/info.0.json";

// This function runs if the http://localhost:5000/getData endpoint
// is requested with a GET request
app.get('/getData', cors(corsOptions), async (req, res) => {
    const fetchOptions = {
        method: 'GET'
    }
    const response = await fetch(requestEndpoint, fetchOptions);
    const jsonResponse = await response.json();
    res.json(jsonResponse);
});

app.listen(PORT, () => {
    console.log(`Example app listening at http://localhost:${PORT}`);
});

```

So, let's go through the code.

We first set our port to 5000, as we need it to be separate from the port we use on our front-end React App, which was defaulted to port 3000.

```javascript
const PORT = 5000;
```

Express commonly uses [routing](https://expressjs.com/en/guide/routing.html) that defines how the server's endpoints will respond to our front-end React App's requests. In this case, we've defined how the server will react when the endpoint `http://localhost:5000/getData` is accessed with a GET request.


```javascript
app.get('/getData', cors(corsOptions), async (req, res) => {
  //...
});
```

But by default, our Express server will return CORS errors if accessed from our front-end React App that lies on a different domain (port). By setting up some CORS options, we allow requests from port 3000 to access our resources that lie on `http://localhost:5000/getData`.

```javascript
app.use(cors());
const corsOptions = {
    origin: "http://localhost:3000"
};

app.get('/getData', cors(corsOptions), async (req, res) => {
  //...
});
```

If we were to access `http://localhost:5000/getData` with a GET request from our React App, Express will run the related function, which in this case would be a fetch request to the xkcd REST API endpoint. As this request is made from the server side, it does not run in to any CORS errors. The response from xkcd is obtained, and returned back to our React App through the `res.json()` method.

```javascript
const fetchOptions = {
    method: 'GET'
}
const response = await fetch(requestEndpoint, fetchOptions);
const jsonResponse = await response.json();
res.json(jsonResponse);
```

OK, now that's ready, let's start running the express server!

```
node server.js
```

We can quickly see if it's running successfully by accessing `http://localhost:5000/getData` through the browser. We should see the JSON response being displayed.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzruspd9ek0ozp3snu2h.png)

OK, so it looks like the Express App is making successful REST API calls to `https://xkcd.com/327/info.0.json`. Note that if we want to make any changes to **server.js**, we should restart the App to see the changes take place.

Let's leave the Express server running, and return back to our React code so that it points to the Express App rather than directly to the xkcd server.

## Update the React code

There isn't much to do here, except for updating our REST endpoint to our Express server instead of the xkcd endpoint.

```javascript
// const restEndpoint = "https://xkcd.com/327/info.0.json";
const restEndpoint = "http://localhost:5000/getData";
```

Refresh the browser, and let's see if we've managed to bypass the CORS error.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2vvq6bjwi1yhnrcvjlrc.png)

Great! The REST API response has successfully rendered onto our HTML, and there are no CORS errors in our console.

And with that, we've managed to successfully avoid CORS errors to make REST API calls to xkcd by using our Express server as a proxy!

# <u>Next steps</u>

In the next part of the series, we'll make a REST API call to a Web Database service, Kintone, which will challenge us to our next issue.

                       ＿人人人人人人人人人＿
                       ＞ AUTHENTICATION ＜
                       ￣Y^Y^Y^Y^Y^Y^Y^Y￣
                       (\__/) 
                       (•ㅅ•) 
                       /つ つ