0
votes

I am trying to access an API from the front-end and i tried both xhr and fetch api requests.

When using fetch, i received the error "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:5500' 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."

However, when using XHR, I do not receive a headers not present warning and it sucessfully fetches the JSON from the api.

I don't quite understand CORS, but my understanding is that there was no header present on the api I was requesting and therefore could not fetch the API. BUT, how was xhr able to fetch the api with the assumed lack of headers on the API? How was the request possible in an XMLHTTPRequest but not a fetch request? How would I use fetch to fetch this API? I have included both my fetch and XHR code below for reference.

Fetch Code:

fetch(requestURL, { 
    headers: {
        "Content-Type": "application/json",
        'Authorisation': 'Basic' + apiKeySecured,
        "Access-Control-Allow-Origin": "*", // Required for CORS support to work
        "Access-Control-Allow-Credentials": false,
        "api-key": apiKeySecured,
    }
}).then(function (response) {
    return response.json();
})
    .then(function (myJson) {
        console.log(JSON.stringify(myJson));
    })
    .catch(error => console.error(error));

XHR code:

var xhr = new XMLHttpRequest();
xhr.withCredentials = false;

xhr.addEventListener("readystatechange", function () {
    if (this.readyState === this.DONE) {
        console.log(this.responseText);
    }
});

xhr.open("GET", requestURL);
xhr.setRequestHeader(`api-key`, apiKeySecured);

xhr.send();
2
your issue is You don't know CORS ... see this "Access-Control-Allow-Origin": "*", // Required for CORS support to work ... nope, that's what is causing the preflight - that's a response header, don't put it in a request (don't manually add any Access-Control headers in your request, EVER - Jaromanda X
in fact, the ONLY header you should add is api-key ... then you're making the same fetch request as XHR - currently you're adding 4 extra headers in fetch compared to XHR - Jaromanda X

2 Answers

0
votes

You need to set the mode option for fetch.

From the docs:

// Example POST method implementation:

postData(`http://example.com/answer`, {answer: 42})
  .then(data => console.log(JSON.stringify(data))) // JSON-string from `response.json()` call
  .catch(error => console.error(error));

function postData(url = ``, data = {}) {
  // Default options are marked with *
    return fetch(url, {
        method: "POST", // *GET, POST, PUT, DELETE, etc.
        mode: "cors", // no-cors, cors, *same-origin
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin", // include, same-origin, *omit
        headers: {
            "Content-Type": "application/json; charset=utf-8",
            // "Content-Type": "application/x-www-form-urlencoded",
        },
        redirect: "follow", // manual, *follow, error
        referrer: "no-referrer", // no-referrer, *client
        body: JSON.stringify(data), // body data type must match "Content-Type" header
    })
    .then(response => response.json()); // parses response to JSON
}
0
votes

What is triggering the pre-flight in your original code?

Every single one of those extra headers you added

"Content-Type": "application/json",
'Authorisation': 'Basic' + apiKeySecured,
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Credentials": false,

Not one of these was added to XHR, so don't add it to fetch

Your fetch should be

fetch(requestURL, { 
    headers: {
        // remove all those random headers you added
        "api-key": apiKeySecured
    },
    mode: 'cors' // add this 
}).then(response => response.json())
.then(function (myJson) {
    console.log(JSON.stringify(myJson));
})
.catch(error => console.error(error));

Now it is equivalent to your XHR code