Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to catch 403 in try-catch during fetch

I'm making a put request using ReactJS, however, when I put in the wrong email/password combination, I get this logged on Chrome, even though I'm trying to catch all errors and show them in errorDiv:

enter image description here

async connect(event) {
  try {
    const userObject = {
      username: this.state.userName,
      password: this.state.password
    };
    if (!userObject.username || !userObject.password) {
      throw Error('The username/password is empty.');
    }
    let response = await fetch(('someurl.com'), {
      method: "PUT",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(userObject)
    });
    let resJSON = await response.json();
    if (!response.ok) {
      throw Error(resJSON.message);
    }
    console.info(resJSON.message);
    console.info(resJSON.message.auth_token);
    window.location = "/ledger/home";
  } catch (e) {
    document.getElementById("errorDiv").style.display = 'block';
    document.getElementById("errorDiv").innerHTML = e;
  }
}
like image 914
Muhammad Ali Avatar asked Sep 22 '18 15:09

Muhammad Ali


People also ask

How do you deal with failure to fetch?

The fetch() function will automatically throw an error for network errors but not for HTTP errors such as 4xx or 5xx responses. For HTTP errors we can check the response. ok property to see if the request failed and reject the promise ourselves by calling return Promise.

Why do I keep getting 403 Forbidden?

The 403 Forbidden error appears when your server denies you permission to access a page on your site. This is mainly caused by a faulty security plugin, a corrupt . htaccess file, or incorrect file permissions on your server.

How can I get the status code from an HTTP error in fetch?

To get the status code of an HTTP request made with the fetch method, access the status property on the response object. The response. status property contains the HTTP status code of the response, e.g. 200 for a successful response or 500 for a server error.


2 Answers

As per the mdn, fetch will throw only when a network error is encountered.
404 (or 403) are not a network error.

The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.

a 404 does not constitute a network error, for example. An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true

like image 99
Sagiv b.g Avatar answered Sep 22 '22 01:09

Sagiv b.g


I completely agree with @Sagiv, but there is a quick workaround to do that, although it is not a suggested way. Inside of try or promise.then(), you need to do this check.

const res = await fetch();
console.log(res);    // You can see the response status here by doing res.status

So, by some simple checks it is possible to resolve or reject a promise. For e.g. in your case

async connect(event) {
  try {
    const userObject = {
      username: this.state.userName,
      password: this.state.password
    };
    if (!userObject.username || !userObject.password) {
      throw Error('The username/password is empty.');
    }
    let response = await fetch('someurl.com', {
      method: 'PUT',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(userObject)
    });
    if (response.status === 403) throw new Error('403 is unacceptable for me!');
    let resJSON = await response.json();
    if (!response.ok) {
      throw Error(resJSON.message);
    }
    console.info(resJSON.message);
    console.info(resJSON.message.auth_token);
    window.location = '/ledger/home';
  } catch (e) {
    document.getElementById('errorDiv').style.display = 'block';
    document.getElementById('errorDiv').innerHTML = e;
  }
}

I strongly recommend using axios. For the fetch issue, you can refer to this link

like image 34
Sourodeep Chatterjee Avatar answered Sep 20 '22 01:09

Sourodeep Chatterjee