Reverse proxy in ReactJs and Vercel - Avoid CORS error in API

Biswajit NayakFollow me on Linkdin linkdin

5 Min Reading,

12

Baby dark lord from star wars!

Introduction

reverse proxy server is a type of proxy server that typically sits behind the firewall in a private network and directs client requests to the appropriate backend server. A reverse proxy provides additional abstraction and control to ensure the smooth flow of network traffic between clients and servers.

Imagine you have a popular website, "nuctro.com", and you want to enhance its performance and security. By setting up a reverse proxy server, incoming requests from users are directed to the reverse proxy instead of the main website. The reverse proxy then forwards these requests to the main website and sends back the responses to the users, all while masking the details of the original server. This setup not only hides the main website's identity but also allows for caching of content to improve performance and filtering of incoming traffic to enhance security. Thus, the reverse proxy serves as a protective shield and performance booster for the website.

How does reverse proxy help in solving CORS errors while fetching an API?

Answer: When your website wants to fetch data from another website's API, your browser often blocks it due to CORS (Cross-Origin Resource Sharing) restrictions. However, by employing a reverse proxy, this hurdle can be overcome. The reverse proxy acts as a middleman, intercepting requests from your website to the API. It then fetches the data from the API on behalf of your website. Crucially, when it sends the data back to your website, it adds special headers to make it seem like the data came from your website itself, bypassing the CORS restrictions. Essentially, the reverse proxy masks the origin of the data, ensuring your browser accepts it without complaints. This way, you can seamlessly integrate external data into your website without worrying about CORS errors.

Assume that your website is running on the domain nuctro.com and all your APIs are hosted on a server with the domain xyzapi.nuctro.com server. To fetch API we are going to use the inbuild JavaScript fetch function.

const response = await fetch("https://api.nuctro.com/api/get-my-data")
response = await response.json()

The above code is an example of how we do in general. Now if someone checks your website in any browser developer network tab. He/She will be able to figure out the endpoint of APIs. This can cause serious security problems. Anyone can use this endpoint and can send unnecessary requests, which is going to increase your bill eventually. To stop this we are going to make our API secure by blocking accessing API directly other than accessing from the Nuctro website. Most browsers do block by throwing CORS when the API domain doesn't match the website domain. In this scenario, we are going to use a reverse proxy technique.

Reverse proxy in localhost

Setting up a reverse proxy in localhost is very easy. Suppose your project is running on localhsot:3000. First, remove the endpoint from the fetch function.

//removed endpoint from URL/removed endpoint from url
const response = await fetch("/api/get-my-data")
response = await response.json()

If you run this, then you can check in your network tab, that all the API endpoints have changed to localhost:3000 and the API response status is 404. This is because we haven't added an endpoint and the browser will take the default domain which will be the domain name of your server which is localhost:3000.

Now add a new key call proxy in your package.json file

 "proxy": "https://xyzapi.nuctro.com",

Now check your network tab. Now your API status has changed from 404 status to its correct status. All though your endpoint is showing localhost, APIs are still working. That's the magic of reverse proxy. This is not the end of your journey, we have just started with reverse proxy.

This technique will only work in development and not in a production environment. Also, you will end up changing all your default endpoints wherever you haven't mentioned the endpoint. Suppose your logo file is inside a public root folder, the browser will not be able to access the file, if you haven't explicitly mentioned the endpoint in the code. Things are getting complicated right? Don't worry we are still in a development environment, a long way to go.

Now you can remove the proxy key from your package.json and install http-proxy-middleware package in your project

npm i http-proxy-middleware

Create a file setupProxy.js inside your src folder.

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'https://xyzapi.nuctro.com',
      changeOrigin: true,
    })
  );
};

Above function will check the url that's starts with /api if find one then reverse proxy is applied to the url, you can also add multiple condition in this function e.g.

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/assets',
    createProxyMiddleware({
      target: 'https://ik.imagekit.io/133545345',
      changeOrigin: true,
    })
  );
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'https://xyzapi.nuctro.com',
      changeOrigin: true,
    })
  );
};

Reverse proxy using versel.json for the app deployed in Vercel

http-proxy-middleware package will work perfectly in both production and development environments, it doesn't matter where it is deployed. But in case if your app is deployed in vercel then there is another way to apply reverse proxy, using versel.json file. Create a versel.json file inside root folder of your project, your root folder is not the src folder.

{
    "rewrites": [
      {
        "source": "/api/:path*",
        "destination": "https://xyzapi/nuctro.com/api/:path*"
      },
      {
        "source": "/assets/:path*",
        "destination": "https://ik.imagekit.io/123343dfd/assets/:path*"
      }
    ]
  }

Happy Coading!