ChatGPT解决这个技术问题 Extra ChatGPT

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.

The 3rd party server needs to set it, there is nothing you can do on the clientside.
@epascarello: We can do at the client side. Behind the scene, XHR Request is going on. Please check this https://davidwalsh.name/fetch

D
David

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)  
});

can you elaborate on "However this still requires the server to enable CORS as well, and allow your domain to request the resource."? I've been unsuccessfully looking for instructions to do that.
@jayscript the overall process looks like this: on the client, a cross origin request is made with javascript. In the case of the fetch API, 'cors' mode tells the browser that its okay to make this request. If you had 'no-cors' mode instead, the browser would stop the request, because it is not to your app's origin. The server will receive the request and respond. The browser confirms that the response has the appropriate CORS headers, and if so, allows the response to be read. If the headers are not present, the browser will throw an error.
@jayscript this MDN article goes into detail. Essentially, one your server you need set these headers: "Access-Control-Allow-Origin: foo.example", "Access-Control-Allow-Methods: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type", which enable origins, methods, and headers respectively. Typically '*' is used for the origin header.You can also check this Google document and associated codelab to learn about the Fetch API: developers.google.com/web/ilt/pwa/working-with-the-fetch-api
Thank you! That help me understand that it is impossible to fetch data from the API server that has a different origin when the API server does not contain any headers. In the particular case I was dealing with, I had access to the API server code and was able to add headers by myself, which enabled fetching.
This is dumb, what's the security issue with NO sending cookies and thus allowing CORS?
V
VigKam

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!


Pls make sure the server is running parallel Like open new cmt-prompt window and run the code lcp --proxyUrl yourdomain.com
This is great, Save my day
Not sure how this works but it does!...:-).. thanks @VigKam
s
smsivaprakaash

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.


this is a terrible answer. this is a massive security issue. if you are reading this, PLEASE DO NOT DO THIS.
This is ly for the local setup. For example to do a quick pic kinda. Yes there is a security risk if the same goes for other deployable environments. For local I feel it doesn't."However you should restrict the you origins in case of other environments like stage, prod"
@MatJones you forgot to tell us what to do
@DapoMichaels set the values to the actual strict values you want to allow. not just *
@MatJones this is only for a local setup."Strictly NO for higher environments."
M
MattG

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)
});

M
Muhammad Saadat Ataa

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'

O
O.Caliari

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;
    }


M
Marek Szkudelski

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.


How can you know if it is OP's server and it is written in NodeJs?
If you have created a node server (development mode), you can use that method to use fetch in js.