How to create a proxy in React/Webpack to call an external API

Viewed 16219

I want to issue a GET request to an external API that I do not control. Because of the security on the API, my react app cannot directly make an ajax request to the endpoint. Therefore I'm trying to create a simple proxy as demonstrated here

My package.json file looks like this:

{
  "name": "my-stack",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-router-dom": "^4.2.2",
    "react-scripts": "1.0.13"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "proxy": {
    "https://gold-feed.com/paid/*": {
        "target": "https://gold-feed.com/paid",
        "changeOrigin": true
    }
  }
}

And then my ajax request looks like this:

const apiUrl = 'https://gold-feed.com/paid/<apiID>/all_metals_json_usd.php';

jQuery.ajax({
  method: 'GET',
  url: apiUrl,
  success: (item) => {
    this.props.addItem(item);
  }
});

But it doesn't appear to be doing anything. I'm still getting the following error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

I essentially have the same issue as documented here where he is trying to create a proxy to access the Steam api.

And just a side note, I believe the create-react-app project that I'm using is piggybacking off of webpack.

3 Answers

For my case my api was deployed on AWS, I found that setting

"changeOrigin": true

was necessary (chrome & edge worked, firefox (62.0.3) complained "Invalid CORS request").

In the documentation of webpack http proxy they say this option: (https://github.com/chimurai/http-proxy-middleware)

Tip: Set the option changeOrigin to true for name-based virtual hosted sites.

notes:

  • running the api locally on same machine didn't require that for fire fox.
  • firefox adds header "origin" which when I removed and resent the request worked.
  • adding "changeOrigin" doesn't have side effects so I will be doing it from now on.

I'm not sure if it's a bug in firefox or what, anyway my final configuration was:

"proxy": {
  "/api": {
    "target": "<put ip address>",
    "changeOrigin" : true
  }
}

you should replace /api with the path of your api or rewrite the path as the answer above.

You can proxy external API to localhost, change frontend origin (localhost:3000), target server, update token if needed and run following script in node js

const express = require('express');
const proxy = require('express-http-proxy');
const cors = require("cors");

const app = express();

app.use(
  cors({
    origin: 'localhost:3000',
    credentials: false
  })
);

app.use('/', proxy('https://www.targetserver.com/', {
  proxyReqPathResolver: function (req) {
    return req.url;
  },
  proxyReqOptDecorator: function (proxyReqOpts, srcReq) {
    proxyReqOpts.headers = {'Authorization': 'Replace with JWT'};
    return proxyReqOpts;
  }
}))

app.get('/*',function(req,res,next){
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});


app.listen(4000, () => console.log(`Server Listening on port ${4000}!`));

Use it in your fontend application like this (with axios or fetch) :

axios.get('http://localhost:4000/api/route).then(x => console.log(x));
Related