0

I am learning react, I currently have a .net core API running in visual studio on localhost:7071.

The Local API is not running cors as there is no requirement for it to use Cors.

Creating a simple react client using the following will not return data due to a cors error?

I have tried a number of solutions online and none of them work, so how can I make this "simple" react client work without generating the following error

Access to XMLHttpRequest at 'http://localhost:7071/api/Users' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.



function GetApiResults(){
    const axios = require('axios').default;
    axios.defaults.headers.common["Access-Control-Allow-Origin"] = "*";


    axios({
        method: 'get',
        headers: { 'Content-Type': 'application/json' },
        url: 'http://localhost:7071/api/Users',
      }).then(function (response) {
        console.log(response.data);
      })
      .catch(function (error) {
        // handle error
        console.log(error);
      })
      .then(function () {
        // always executed
    });
      
}

export default GetResults;
Psymon25
  • 336
  • 2
  • 18

3 Answers3

1

You have a pretty straighforward description of the issue, browser expects the external resouces you are using (API in your case, external in terms it is not on same port) to provide CORS headers. If they are not set - browser will not execute the request. It will execute the request if you open the resource URL in browser tab, but if you are on localhost:3000 - any requests initiated by this page to anything that is not on localhost:3000 will require CORS to be set.

https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-6.0

Browser security prevents a web page from making requests to a different domain than the one that served the web page. This restriction is called the same-origin policy. The same-origin policy prevents a malicious site from reading sensitive data from another site.

So either enable CORS support in your backend, either use CRA feature called Proxy: https://create-react-app.dev/docs/proxying-api-requests-in-development/

I prefer the manual proxy configuration, at the very end of the article.

Important: this proxy is for DEVELOPMENT only!

Here is a step-by-step instruction, just tested:

  1. Install npm install http-proxy-middleware --save

  2. Add src/setupProxy.js with content:

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

module.exports = function (app) {
  app.use(
    "/api",
    createProxyMiddleware({
      // I have a different port and Visual Studio might randomly change it
      // Fix: edit running configuration 
      // https://stackoverflow.com/questions/70332897/how-to-change-default-port-no-of-my-net-core-6-api

      // Notice: no /api at the end of URL, it will be added.
      // more details at: https://www.npmjs.com/package/http-proxy-middleware
      target: "https://localhost:7002",
      changeOrigin: true,

      // Im using .net core 6 starting api template
      // which is running with a self-signed ssl cert with https enabled
      secure: false 
    })
  );
};

  1. Modify your AXIOS configuration object to use new URL:
function GetApiResults() {
  const axios = require("axios").default;
  axios({
    method: "get",
    headers: { "Content-Type": "application/json" },
    url: "/api/WeatherForecast"
  })
  /* ... */
}

Note: Im using default web api project, only changed [Route("api/[controller]")] (added api/) for Controller.

  1. Restart the app and watch for logs from npm start output, proxy can log some errors there.
Sergey Sosunov
  • 4,124
  • 2
  • 11
  • 15
  • I think i am clearly stupid as i could not get this working either :( followed the guide added proxy to the packages.json too and the proxy did not route. i fixed this by using a cors plugin for chrome: https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf/related?hl=en – Psymon25 Aug 23 '22 at 14:51
  • thanks @Sergey Sosunov I went straight for the manual setup but for some reason on my dev machine i just couldn't get it going, I did realise the setupProxy.js does not hot reload so did restart i copied the example straight out of the link you provided and then adjusted to match http://localhost:7071 with the axios call reduced to have just the params needed based on the example but it would call localhost:3000 instead and not redirect to the proxied address so went with the above unsafe option for dev (i am learning react while trying to use a .net API in a sandbox) – Psymon25 Aug 23 '22 at 15:34
  • Thanks again @SergeySosunov I will give this a try tomorrow; I genuinely appreciate the extra mile you have gone through to assist my learning and much kudos to you for your patience :D – Psymon25 Aug 23 '22 at 19:56
  • 1
    i just tested and working great, i actually experienced the same issues at first then realised by cloning the weather app and comparing with the above my mistake... Where /api was indicated as the entry point in the setupProxy.js file i then excluded that from the axios URL thinking all requests were proxied (doh requests were still routed to 3000), on realising the mistake i added /api/WeatherForecast as above, back to the axios function and it all worked fantastically well; it was that realisation that the setupProxy is looking for URLs starting with the configured endpoint in this case api – Psymon25 Aug 24 '22 at 09:45
0

CORS is a browser feature. So, the browser you are using to access the React app must require you to use CORS. You need to setup CORS on your backend and allow connections from remote origin.

0

It will be good if you add CORS enabling code on Server Side. if your server-side app is in Express JS then add below middleware-

var app = express();

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");

  //  res.header("Access-Control-Allow-Origin", "http://localhost:3000"); or add your react app url.
  next();
});