73

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
  • 16,571
  • 12
  • 101
  • 98
Scott Davidson
  • 995
  • 1
  • 9
  • 12
  • 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

18 Answers18

34

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
  • 20,056
  • 7
  • 57
  • 79
  • @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
  • 2
    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
25

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

mufazmi
  • 1,103
  • 4
  • 18
  • 37
Colleen Purcell
  • 473
  • 5
  • 7
24

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 (you only need to change the port in url):

    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.

  • 1
    My app is react and js without express.. should I install express to fix the problem? – Bahaa Salaheldin Apr 06 '23 at 20:56
  • No, these are completely different beasts. You create a standalone webserver acting as a proxy between your app (different port on a localhost) and the server (different domain). `onProxyRes` simply catches the original server response and masks it so that client thinks it has `Access-Control-Allow-Origin *` which is not the case for a protected server. – Jiří Sep 02 '23 at 09:13
  • For example, I created a new node.js app inside my project root (`/cors-proxy/index.js`) and addded (here for windows) expo launcher script: `"web": "cd cors-proxy && start cmd.exe /c node index.js && cd .. && expo start --web --port=8080"` – Jiří Sep 02 '23 at 09:16
10

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
  • 568
  • 4
  • 7
9
        //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
  • 1,018
  • 1
  • 11
  • 16
6

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
  • 89
  • 2
  • 7
4

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
  • 1,377
  • 1
  • 8
  • 13
  • 7
    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
4

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
  • 16,571
  • 12
  • 101
  • 98
  • 1
    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
  • 5,844
  • 10
  • 37
  • 55
1

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
  • 5,174
  • 11
  • 43
  • 74
1

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
  • 11
  • 4
1

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
  • 510
  • 6
  • 8
1

This is a common issue occurs when you try to call an endpoint via your react app because react app is running on localhost:3000 and apis are on different servers.

to rectify this error install 'http-proxy-middleware'

npm i http-proxy-middleware 
or
yarn add http-proxy-middleware

after installation create a setupProxy.js in your src folder

and follow below code

    const { createProxyMiddleware } = require('http-proxy-middleware');
    
    module.exports = function(app) {
    
        app.use(
        '/getDetails', //this is your api
        createProxyMiddleware({
          target:'http://10.0.0.20:9000/getDetails', //this is your whole endpoint link
          changeOrigin: true,
        })
      );


    app.use(
        '/getproducts', //this is your api
        createProxyMiddleware({
          target:'http://10.0.0.20:9000/getproducts', //this is your whole endpoint link
          changeOrigin: true,
        })
      );
      
    };

you can add as many api as you want in app.use. and then just normally call the api

axios.get('http://10.0.0.20:9680/getDetails')

for more details check below link Porxying API requests in Development in React JS

Aniket Deshpande
  • 279
  • 1
  • 5
  • 14
1

use below after private property in package.json.

"proxy": "http://localhost:5000", 

The Key is proxy and the value is your server URL

AND other thing is Chrome does not support localhost to go through the Access-Control-Allow-Origin chrome isse cors

OR

If you use Express please add routes after use cors

app.use(cors());  
app.use('/posts', postRoutes);
Dhia Djobbi
  • 1,176
  • 2
  • 15
  • 35
0

In my case I was getting the CORS error even after enabling it on server side. The issue was url. localhost:4001/todos I forgot to prepend the 'http'.

http://localhost:4001/todos //correct way

You don't have to deal with it on client side. Just need the following steps:

Step 1:

npm install cors

Step 2:

//express-server.js  

...
const cors = require('cors');
app.use(cors());

Done!

Anil Singh
  • 4,293
  • 2
  • 24
  • 19
0

Add proxy to package.json file and keep the remaining part of url in the fetch itself.

eg.,

In package.json file, "proxy" : "https://www.google.com", //add your own website link

In App.js file const response = await fetch(./...(as per your own))

newbie
  • 1
0

add this to your server.js in your express app

const cors=require("cors");
 const corsOptions ={
       origin:'*', 
       credentials:true, //access-control-allow-credentials:true
        optionSuccessStatus:200,
 }

 app.use(cors(corsOptions)) 

make sure to run npm install cors

0

I fixed the same problem by simply installing "cors" in my server folder. I used express to create an api and tried to send get request to the api but it did not work without "cors".

johnnn
  • 71
  • 1
  • 4