How to Make a Fetch Proxy in Javascript to Avoid CORS Errors with APIs

crashdaddy
4 min readApr 13, 2020

--

Are you tired of CORS errors? Of course. We all are.

How many times have you gotten all excited about a new API only to discover that when you try to get the data all you seem to end up with is this nonsense cluttering up your console?

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at $somesite

What’s the problem? The problem is that the server that is providing the API has not been set up to allow CROSS-ORIGIN-RESOURCE-SHARING (“CORS,” get it?).

And it might not be an accident on the part of the server administrator at the API. They might have it disabled for some reason, even though common sense suggests that goes against the spirit of providing a public API in the first place.

Here’s what developer.mozilla.org has to say about it:

For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from, unless the response from other origins includes the right CORS headers.

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.

I made a repl.it to demonstrate the principle.

// build a function to retrieve data from an API!const getData = () => {
// the API endpoint
let url = “https://bing.com/covid/data";
// call the API
fetch(url)
.then(res => res.json())
.then(data => {
const entries = Object.entries(data)for(var [key,value] of entries) {
document.getElementById(“output”).innerHTML += key+”: “ + value + “<br/>”;
}
})
.catch(error => {
console.log(error.message);
})
}
// call dat function!
getData();

All this does is…nothing, because it returns a CORS error. What it should be doing is requesting the API, looping through the object and outputting the keys and values to a div called “output.”

Of course, if you’ve already run into that problem a time or two or a thousand, then you’ve discovered this nifty little tool to circumvent the CORS error.

By simply adding “https://cors-anywhere.herokuapp.com/” in front of the API URL you will be calling a proxy server that will send the request on your behalf and then return the data to you.

Try it on that repl.it above and you’ll see it’s a pretty easy solution, but today we’re going to build our own API Proxy.

Why? I’m glad you asked. Because:

  1. herokuapp has rate-limits on their cors-anywhere link. Last I checked it was down to two-hundred hits/hour. That might sound like a lot during development, but what about when your exciting app takes off and two-hundred and one people want to use it?!
  2. building your own proxy gives you more flexibility and control into its design and implementation
  3. you’re a computer programmer and you like programming computers

We’re going to build our Fetch Proxy on repl.it, but you can build it on your own server if it provides NodeJS, ExpressJS and Axios.

Here’s the Fetch Proxy we’re building:

Looks pretty simple, right? It is! Let’s break down the code.

const express = require(‘express’);
const axios = require(‘axios’);
const bodyParser = require(‘body-parser’);
const cors = require(‘cors’);
const CircularJSON = require(‘circular-json’);
const app = express();app.use(bodyParser.json());app.use(bodyParser.urlencoded({ extended: true }));app.use(cors());// call the APIapp.get(‘/’, (req, res) => {axios.get(‘https://bing.com/covid/data').then(data => {res.send(CircularJSON.stringify(data.data));}).catch(error=> {console.log(error.message);})});app.listen(3000, () => console.log(‘server started’));

I took out the comments for brevity.

What are we doing? First we’re requiring “ExpressJS” so it will act like a server and be ready whenever anybody needs it. You won’t need to keep your repl.it open or do anything weird like that. It’s just ready to work when called.

Here’s how you call it: https://CORS-buster--crashdaddy.repl.co

So in other words, when you go to fetch the data from the API you’re wanting, just use that link instead of the API endpoint. Then the server calls the API using the AXIOS “get” method and returns the data to you.

This is because the AXIOS “get” method is not constrained by the same CORS rules that prevent your usual fetch from working.

Then when the data is returned, we just hand it to you to do what you want with it:

res.send(CircularJSON.stringify(data.data));

You won’t always need “CircularJSON,” but this API does need it to parse the results properly. Usually you can just stringify the data and res.send it and you’re done!

The last line is how express does all this goodness without you having to be involved all the time or keeping your repl.it open:

app.listen(3000, () => console.log(‘server started’));

Now that you can build your own proxy, that’s one less external dependency to worry about. Plus you can customize it for any APIs you need to, and the only rate limits you’ll ever experience are the ones you impose (once you’ve put it on your own server.)

Here’s a live example of me using this method.

Here’s my proxy that calls the Bing Covid API. You can fork that and just change the API URL to any API you want and it’ll work just fine.

And here’s where you can buy me coffee!

Thanks for your support!

--

--

crashdaddy

4a 75 73 74 20 61 6e 6f 74 68 65 72 20 63 6f 6d 70 75 74 65 72 20 6e 65 72 64 20 77 69 74 68 20 61 20 62 6c 6f 67