A CORS Workaround Proxy for React Apps Supporting Dynamic Hosts

Terris Linenbach
2 min readDec 25, 2020

Applications created by create-react-app (CRA) include an Express-based proxy for working around cross-origin security in web browsers. This capability is described in Proxying API Requests in Development.

The CRA-provided proxy works well for static host names. However, if the URL (particularly the host name) of an external service depends upon data acquired at runtime, you will need to do some extra work.

Why would you need dynamic host names? You shouldn’t in most cases. But if your application needs to, say, choose from a list of geographically distributed hosts based on input data, you need a more permissive proxy.

Can you trust a third-party to provide your application with the URL of a reputable external service, even during development? If not, proceed no further. You have been warned.

Add the request package

Add the request package as a devDependency.

npm i --save request

Add setupProxy.js

Add setupProxy.js to the application’s src directory. This tiny proxy forwards GET requests sent to localhost:3000/forward to the URL in the X-Forward header. Do the same for post, put, etc., if you need them.

const request = require('request');module.exports = (app) =>
app.get('/forward', (req, res) => {
const { headers } = req;
const uri = headers['x-forward'];
delete headers['x-forward'];
delete headers.host; // Needed to work with https
try {
request({
uri,
headers,
})
.on('error', (error) =>
res.status(503).send(error.message))
.pipe(res);
} catch (error) {
res.status(400).send(error.message);
}
});

Modify the application

When invoking the external service, use the static URL /forward and pass the real URL via the X-Forward header. Here’s an example:

const headers = new Headers({
'X-Forward': 'https://api.github.com/repos/tannerlinsley/react-query' });
fetch('/forward', { headers });

This code will probably only execute during development. Here’s one recommended way to detect whether your application is running in development mode:

isDev.js

const process = require('process');module.exports = !process.env.NODE_ENV || process.env.NODE_ENV === 'development';

Example

Better ideas?

If you have a better solution, please respond to this article!

--

--

Terris Linenbach

He/him. Coder since 1980. Always seeking the Best Way.