38

I'm running into an issue with my isomorphic JavaScript app using React and Express.

I am trying to make an HTTP request with axios.get when my component mounts

componentDidMount() {
  const url = 'http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders';
  axios.get(url).then( res => {
    //use res to update current state
  })
}

I am getting a status 200 res from the API, but I am not getting any response data and getting an error in my console

XMLHttpRequest cannot load http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.

However, if I make the request in my server.js

const url = 'http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders';
axios.get(url).then(res => {
    //console.log(res);
});

It works fine and I get response data when the server starts. Is this an issue with the actual API or am I doing something wrong? If this was a CORS issue I'm guessing the request in server.js wouldn't work either? Thanks!

Ahmad Aghazadeh
  • 14,753
  • 10
  • 88
  • 89
Scott Davidson
  • 537
  • 1
  • 6
  • 11
  • If someone has the error when testing locally there are many answers in https://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome/45433997#45433997 – Michael Freidgeim May 08 '20 at 21:58

12 Answers12

21

Use the google Chrome Extension called Allow-Control-Allow-Origin: *. It modifies the CORS headers on the fly in your application.

Colleen Purcell
  • 383
  • 3
  • 7
20

CORS is a browser feature. Servers need to opt into CORS to allow browsers to bypass same-origin policy. Your server would not have that same restriction and be able to make requests to any server with a public API. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Create an endpoint on your server with CORS enabled that can act as a proxy for your web app.

azium
  • 17,620
  • 5
  • 44
  • 73
  • @Todd security should always come before convenience. Luckily provisioning proxy servers can be a 5 minute exercise. Additionally there are proxy services that expose this type of functionality already but only allow so many free requests. Setting up your own proxy is worth the extremely minimal effort. – azium Feb 21 '18 at 21:09
  • I've got the same problem and i've read the docs you have mentioned above still don't get idea of CORS can you elaborate it, please – Sagar Gautam Aug 06 '18 at 03:15
  • @SagarGautam Can you make a new stackoverflow question and mention everything you're having trouble understanding, then comment here with the link to your post? I'll be happy to answer – azium Aug 06 '18 at 04:22
  • I've asked question here please have a look https://stackoverflow.com/questions/51701630/typeerror-networkerror-when-attempting-to-fetch-resource – Sagar Gautam Aug 06 '18 at 06:23
  • I have the same issue.In my case I can create records from desktop computer web browser but cannot create through my iPhone web browser. – chk.buddi Jan 06 '19 at 16:09
8

Fix Without Using External Proxy or Chrome Extension

CORS should be enable in server side! if you can not activate it on server (for example using external API) create a middleware React -> Middleware -> Orginal Server.

  1. Create a Node.js project (Middleware) and use below code in app.js.

    const express = require("express");
    var cors = require('cors')
    const app = express();
    app.use(cors());
    const { createProxyMiddleware } = require('http-proxy-middleware');
    app.use('/api', createProxyMiddleware({ 
        target: 'http://localhost:8080/', //original url
        changeOrigin: true, 
        //secure: false,
        onProxyRes: function (proxyRes, req, res) {
           proxyRes.headers['Access-Control-Allow-Origin'] = '*';
        }
    }));
    app.listen(5000);
    

This will pass the request http://localhost:5000/api/xxx to original server (for example http://localhost:8080/api/xxx), and returns the result to client.

  1. Change client (React) to call proxy and get data without CORS error:

    axios.get('http://localhost:5000/api/xxx', //proxy uri
    {
       headers: {
          authorization: ' xxxxxxxxxx' ,
          'Content-Type': 'application/json'
       } 
    }).then(function (response) {
       console.log(response);
    });
    
  2. run node project node app.js and react project npm start.

4
        //install cors using terminal/command  
        $ npm install cors

        //If your using express in your node server just add
        var cors = require('cors');
        app.use(cors())


       //and re-run the server, your problem is rectified][1]][1]
       **If you won't be understood then see below image**

https://i.stack.imgur.com/Qeqmc.png

HandyPawan
  • 638
  • 1
  • 7
  • 11
3

I had the same problem. the other answers are correct but there is another solution. you can set response header to allow cross-origin access. according to this post you have to add the following codes before any app.get call:

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

this worked for me :)

arash nadali
  • 371
  • 1
  • 6
3

You can use this code when using vs code on debugging mode.

"runtimeArgs": ["--disable-web-security","--user-data-dir=~/ChromeUserData/"]

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Chrome disable-web-security",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "runtimeArgs": [
        "--disable-web-security",
        "--user-data-dir=~/ChromeUserData/"
      ]
    }
  ]
}

Or directly run

Chrome --disable-web-security --user-data-dir=~/ChromeUserData/

Ahmad Aghazadeh
  • 14,753
  • 10
  • 88
  • 89
  • Do you have idea how to make vsc use this configuration automatically when i run "npm start" ? I must use F5 to make chrome use launch.json. Thanx – Kviz Majster Mar 14 '21 at 19:40
2

I think the answer for your question is here

To have Chrome send Access-Control-Allow-Origin in the header, just alias your localhost in your /etc/hosts file to some other domain, like:

127.0.0.1 localhost yourdomain.com

Community
  • 1
  • 1
Pablo Darde
  • 3,855
  • 6
  • 29
  • 47
2

I was having the same problem with the fetch command. A quick look at the docs from here tells us this:

If the server you are requesting from doesn't support CORS, you should get an error in the console indicating that the cross-origin request is blocked due to the CORS Access-Control-Allow-Origin header being missing.

You can use no-cors mode to request opaque resources.

fetch('https://bar.com/data.json', {
  mode: 'no-cors' // 'cors' by default
})
.then(function(response) {
  // Do something with response
});
Yigit Alparslan
  • 749
  • 4
  • 12
  • 3
    However keep in mind that a response for a no-cors request has a response type of 'opaque', which means that you won't be able to read the data returned from the server – istovatis Apr 10 '20 at 13:43
1

I faced the same error today, using React with Typescript and a back-end using Java Spring boot, if you have a hand on your back-end you can simply add a configuration file for the CORS.

For the below example I set allowed origin to * to allow all but you can be more specific and only set url like http://localhost:3000.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class AppCorsConfiguration {
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}
Loup Ollivier
  • 39
  • 1
  • 7
0

Because the server don't have CORS header, so you are not allowed to get the response.

This is header from API that I captured from Chrome brower:

Age:28
Cache-Control:max-age=3600, public
Connection:keep-alive
Date:Fri, 06 Jan 2017 02:05:33 GMT
ETag:"18303ae5d3714f8f1fbcb2c8e6499190"
Server:Cowboy
Status:200 OK
Via:1.1 vegur, 1.1 e01a35c1b8f382e5c0a399f1741255fd.cloudfront.net (CloudFront)
X-Amz-Cf-Id:GH6w6y_P5ht7AqAD3SnlK39EJ0PpnignqSI3o5Fsbi9PKHEFNMA0yw==
X-Cache:Hit from cloudfront
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Request-Id:b971e55f-b43d-43ce-8d4f-aa9d39830629
X-Runtime:0.014042
X-Ua-Compatible:chrome=1
X-Xss-Protection:1; mode=block

No CORS header in response headers.

Thanh Nguyen
  • 4,481
  • 11
  • 32
  • 64
0

I don't know if this will help but I was getting the same error when remote debugging a react-native application. I was running the debugger on 192.168.x.x:8081. I read a little bit on this Cross-Origin Resource Sharing (CORS) to educate myself on what CORS is. (I'm a beginner) and changed my URL from IP:8081 to localhost:8081 and my issue was resolved.

Mingina
  • 1
  • 3
0

Create-React-App has a simple way to deal with this problem: add a proxy field to the package.json file as shown below

"proxy": "http://localhost:8081",
Piotr
  • 158
  • 2
  • 4