Need help on fetch

Hi,

do you know it when you have an error in your code, which you have done thousand times before and you do not find it? So here I am:

I have a node’s backend which returns a json object. When I test with Postman I get the response:

{
    "sso": "xxx",
    "name": "xxx",
    "roles": [
        {
            "name": "Global Administrator"
        }
    ],
    "functions": null
}

So all good on this side.

Now I want to request this info from the frontend:

            let headers = new Headers();
            headers.append('Content-Type', 'application/json');
            const response = await fetch("http://localhost:8888/" + url , {
                method: 'POST',
                headers: headers,
                mode: 'no-cors',
                body: null,
            });
            if (response.status >= 400 && response.status < 600)
            {
                console.log("Error getting backend data from url: " + url + ". Response status = " + response.status);
                Util.createAlert("Ups, something went wrong. Please try again later.")
                reject();
            }
            else
            {
                console.log(response);
                let data = await response.json();
                console.log(data);
                resolve(data);
            }

which gives me

What the hell is going wrong here?

Ok got it.

the no-cors works different to what I have expected:

Effectively, the response you get from making such a request (with no-cors specified as a mode) will contain no information about whether the request succeeded or failed , making the status code 0. Removing mode from your fetch call will show that the CORS had in fact failed.

So what is the right way to remove the CORS error when fetching from other port on same domain?

From what I’ve read, you need to use response.ok instead of a status check. So this line would be

if (!response.ok)

Hi @Thallius,

I managed to get to the same unexpected end of data error message as you, fetching using no-cors and trying to receive some echoed json data from a php file.

I did find this.

Doing a test (Note: no headers set)

  fetch(
    'http://localhost/json-test/somefile.php',
    {
      method: 'POST',
      body: null
    }
  )
    .then((response) => response.text())
    // parse text as JSON string
    .then((text) => JSON.parse(text))
    .then(console.log)
    .catch(console.log)

I was able to output the JSON data.

Albeit this works, I do feel it is a bit like a using a sticking-plaster. I admit I don’t know enough about CORS or how to configure the server to fix this properly.

Edit: or with async/await

async function fetchJSON(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    const data = await response.text();
    return (data) ? JSON.parse(data) : {};
  }
  catch (error) {
    console.error(error);
  }
}

fetchJSON('http://localhost/json-test/somefile.php')
  .then(console.log)

1 Like

Hi,

Thanks for the answer.

Yes the problem is the content type application/json. When you set this header, the cors check takes effect. This means the browser is sending a kind of „check“ request to the server and the answer must have the Access-Control-Allow-Origin set in the header.

Here is a good explanation how it should work.

Problem is that I tried to set all this headers in the servers answer but it doesn’t work.

I can show my attempts in detail tomorrow when I am back at the desk. Now I am already of work.

1 Like

Here is another link. I’ve only scanned through it, but it looks to be a good read.

Just as an edit:

My memory is so bad, I have been down this route before.

If you omit the headers or set it to application/x-www-form-urlencoded, there is no need for parsing a text file. This worked for me anyway.

async function fetchJSON(url) {
  try {
    const response = await fetch(
      url,
      {
        method: 'POST',
        // or just omit headers
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        mode: 'cors',
        body: null
      }
    );
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    const data = await response.json();
    return data
  }
  catch (error) {
    console.error(error);
  }
}

If I remember correctly you can post data in the body as a FormData object.

1 Like

That’s a really good one. I guess I have an idea now how it should work.

I will test tomorrow and report…

1 Like

Ok,

at the end the solution is easy :slight_smile:

For Nodejs there is a middleware cors package. Just install and add to your Nodejs and your done.

Example for Nodejs express:

import cors from 'cors';
import express from 'express';
var app = express();

var corsOptions = {
    origin: 'http://localhost',
    optionsSuccessStatus: 200 // For legacy browser support
}
app.use(cors(corsOptions));

1 Like

I didn’t know if you were working in node or not on the frontend. Actually had the following tab open yesterday :slight_smile:

Glad you have sorted it.

1 Like