iNikkz
iNikkz

Reputation: 3819

Allow Access-Control-Allow-Origin header using HTML5 fetch API

I am using HTML5 fetch API.

var request = new Request('https://davidwalsh.name/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

I am able to use normal json but unable to fetch the data of above api url. It throws error:

Fetch API cannot load https://davidwalsh.name/demo/arsenal.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Upvotes: 151

Views: 531488

Answers (9)

Muhammad Junaid
Muhammad Junaid

Reputation: 1

The "No 'Access-Control-Allow-Origin' header" error happens when a server doesn’t allow cross-origin requests. To fix this, the server needs to enable CORS. On the client side, you can use mode: 'cors' with the Fetch API or work around it using CORS proxies or custom server configurations. Just be careful not to compromise security, especially in production.

Upvotes: 0

reynaldi
reynaldi

Reputation: 113

The website that you are trying to fetch does not have the appropriate CORS header, namely the Access-Control-Allow-Origin.

This header can only be controlled from the server side, and if the server is not yours, you cannot add it.

It is still possible to fetch the data if you relay your request through your backend. This will work since CORS only exists on the client side (browser). What you can do is to set up an endpoint with the purpose of fetching the target URL. Then you can adjust your frontend to fetch your endpoint instead of directly fetching the target URL.

If your website does not have a backend, you can use a CORS proxy. There is a self-hosted option like cors-anywhere or a hosted option like Corsfix.

With CORS proxy, typically you will add the proxy URL before the URL you are trying to fetch.

fetch("https://proxy.corsfix.com/?https://davidwalsh.name/demo/arsenal.json"); 

(I am affiliated with Corsfix)

Upvotes: 1

David
David

Reputation: 2991

Like epascarello said, the server that hosts the resource needs to have CORS enabled. What you can do on the client side (and probably what you are thinking of) is set the mode of fetch to CORS (although this is the default setting I believe):

fetch(request, {mode: 'cors'});

However this still requires the server to enable CORS as well, and allow your domain to request the resource.

Check out the CORS documentation, and this awesome Udacity video explaining the Same Origin Policy.

You can also use no-cors mode on the client side, but this will just give you an opaque response (you can't read the body, but the response can still be cached by a service worker or consumed by some API's, like <img>):

fetch(request, {mode: 'no-cors'})
    .then(function(response) {
      console.log(response); 
    }).catch(function(error) {  
      console.log('Request failed', error)  
    });

Upvotes: 139

smsivaprakaash
smsivaprakaash

Reputation: 1720

Solution to resolve issue in Local env's

I had my front-end code running in http://localhost:3000 and my API(Backend code) running at http://localhost:5000

Was using fetch API to call the API. Initially, it was throwing "cors" error. Then added this below code in my Backend API code, allowing origin and header from anywhere.

let allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Headers', "*");
  next();
}
app.use(allowCrossDomain);

However you must restrict origins in case of other environments like stage, prod.

Strictly NO for higher environments.

Upvotes: 21

Muhammad Saadat Ataa
Muhammad Saadat Ataa

Reputation: 41

You need to set cors header on server side where you are requesting data from. For example if your backend server is in Ruby on rails, use following code before sending back response. Same headers should be set for any backend server.

headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'

Upvotes: 4

Ernersto Pastori
Ernersto Pastori

Reputation: 31

Look at https://expressjs.com/en/resources/middleware/cors.html You have to use cors.

Install:

$ npm install cors
const cors = require('cors');
app.use(cors());

You have to put this code in your node server.

Upvotes: -3

This worked for me :

npm install -g local-cors-proxy

API endpoint that we want to request that has CORS issues:

https://www.yourdomain.com/test/list

Start Proxy:

lcp --proxyUrl https://www.yourdomain.com

 Proxy Active 

 Proxy Url: http://www.yourdomain.com:28080
 Proxy Partial: proxy
 PORT: 8010

Then in your client code, new API endpoint:

http://localhost:8010/proxy/test/list

End result will be a request to https://www.yourdomain.ie/test/list without the CORS issues!

Upvotes: 30

O.Caliari
O.Caliari

Reputation: 351

If you are use nginx try this

#Control-Allow-Origin access

    # Authorization headers aren't passed in CORS preflight (OPTIONS) calls. Always return a 200 for options.
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Allow-Origin "https://URL-WHERE-ORIGIN-FROM-HERE " always;
    add_header Access-Control-Allow-Methods "GET,OPTIONS" always;
    add_header Access-Control-Allow-Headers "x-csrf-token,authorization,content-type,accept,origin,x-requested-with,access-control-allow-origin" always;

    if ($request_method = OPTIONS ) {
        return 200;
    }

Upvotes: 3

MattG
MattG

Reputation: 1932

I know this is an older post, but I found what worked for me to fix this error was using the IP address of my server instead of using the domain name within my fetch request. So for example:

#(original) var request = new Request('https://davidwalsh.name/demo/arsenal.json');
#use IP instead
var request = new Request('https://0.0.0.0/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

Upvotes: 10

Related Questions