2

I am trying to configure a proxy server ( setupProxy.js ) within a create-react-app using HTTP-proxy-middleware to get access to a weather data API ( api.darksky.net ).

I followed the steps within the React documentation ( https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development#configuring-the-proxy-manually ) but am still having issues with CORS.

I have tried prepending my API URL within my fetch call with 'https://cors-anywhere.herokuapp.com/' ( https://github.com/Rob--W/cors-anywhere/ ) and this is working, but it feels a little corny to me and I'd rather get this working on my own.

Here is the function that is ultimately being called from within componentDidMount:

  fetchWeatherDataAuto = () => {
    let lat = this.state.locInfo.lat;
    let lon = this.state.locInfo.lon; 

    fetch(`https://api.darksky.net/forecast/${apiKey.darkSky_key}/${lat},${lon}`)
      .then(response => response.json())
      .then(response => console.log("Weather Response: ", response));
  }

Here is the code that is my setupProxy.js file:

const proxy = require('http-proxy-middleware');

module.exports = function(app) {
    app.use(proxy("/forecast", {
          target: "https://api.darksky.net/",
          changeOrigin: true
    }));
}

This error is shown in my console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading >the remote resource at >https://api.darksky.net/forecast/{myAPIKey}/9.739>9056,-82.8484079. (Reason: CORS header ‘Access-Control-Allow-Origin’ >missing).

kelly_james
  • 21
  • 1
  • 1
  • 3

2 Answers2

3

There is no need to set a custom proxy in this case...

Simply add this to your package.json:

{
  "name": "test1",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "react-scripts": "2.1.3"
  },
  "proxy": "https://api.darksky.net", // <= add this here...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

Then in your App.js

  componentDidMount() {
    fetch(`/forecast/${YOUR_API_KEY_HERE}/${lat},${lon}`)
      .then(response => response.json())
      .then(response => console.log('Weather Response: ', response));
  }

And it should work... (note that all async calls should be done in the componentDidMount lifecycle method...)

SakoBu
  • 3,972
  • 1
  • 16
  • 33
  • 2
    Success. It seems that I was missing the property in the package.json. From what I was reading in other threads, it was suggested that the 'proxy' property should be _removed_ from package.json, leaving only the proxy server ( setupProxy.js ). – kelly_james Jan 21 '19 at 02:21
  • @RashidIqbal it’s for development as it states in the docs... – SakoBu Feb 29 '20 at 02:04
  • @SakoBu, how to fix this issue with hosted app, my app is hosted in firebase hosting – Rashid Iqbal Mar 01 '20 at 07:21
  • @RashidIqbal You could write a simple proxy server or better yet (since you’re already in the GCC ecosystem) a cloud function that fetches the data and then forwards it to client... CORS is a browser issue server to server it will work... – SakoBu Mar 01 '20 at 10:12
2

proxy is placed wrong in your code, try this instead

app.use("/forecast", 
   proxy({
      target: "https://api.darksky.net/",
      changeOrigin: true
   })
);
Macke
  • 24,812
  • 7
  • 82
  • 118
  • I think proxy function is placed correctly in OP's example. From [the docs](https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually): *"Passing the path to the proxy function allows you to use globbing and/or pattern matching on the path, which is more flexible than the express route matching"*. Although I guess in OPs example, the extra flexibility is not really required. – devklick Sep 11 '22 at 13:47