JS Fetch - cannot get data from BadRequest response [duplicate] - javascript

This question already has answers here:
fetch: Reject promise with JSON error object
(5 answers)
Closed 3 years ago.
I am using React + Redux on the client side and I have the backend in NET CORE.
Client gets data from API using:
return fetch(`api/login`, requestOptions)
.then(response => {
if(!response.ok) {
return Promise.reject(response.json() as Promise<AuthError>);
} else {
return response.json() as Promise<ILoginResponse>
}
})
requstOptions are:
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
};
When the password is wrong, the server returns
404 Bad request
and the body is:
{"errorCode":2,"description":"Invalid Password"}
I would like to read the body but with this code, it is not possible because this response.json() as Promise<AuthError> produces an empty object.
Is there a way how to read the body of a bad request response?

As per the Fetch Documentation:
"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."
What you can also check is the Response object documentation. In there, you can check if the Response ok is set to false (so, in a then clause check the response.ok) and from that point on you can check the Response.text property. Check also the Response Documentation

Have you tried using catch and then inspecting error object?
...
.then(response => response.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.dir(error));

Related

I am having trouble making a simple POST Request [duplicate]

This question already has answers here:
Empty body in fetch POST request
(5 answers)
Trying to use fetch and pass in mode: no-cors
(9 answers)
Closed 3 months ago.
I am trying to do a simple call to an API endpoint using the following code and keep getting the following error:
POST net::ERR_ABORTED 400 (Bad Request)
SyntaxError: Unexpected end of input
The request options
const requestOptions = {
method: 'POST',
mode: 'no-cors',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: email,
password: password
})
};
The fetch request
await fetch("https://dev.rapptrlabs.com/Tests/scripts/user-login.php", requestOptions)
.then(async response => await response.text())
.then(response => response === "" ? {} : JSON.parse(response) )
.catch(e => {
console.log(e)
})
I am not sure what I am doing wrong.
Edit: I was only provided with the following documentation:
a. When the form has been successfully submitted passing all
validation errors, call the following API:
http://dev.rapptrlabs.com/Tests/scripts/user-login.php i. This API
endpoint needs to be called with a POST request. ii. It takes two body
params: email and password. iii. For testing purposes, use the
following email and password: test#rapptrlabs.com / Test123. iv. A
successful response will look like the following:
{ "user_id": 16,
"user_email": "test#rapptrlabs.com",
"user_username": "testuser",
"user_is_active": 1,
"user_profile_image": "http://dev.rapptrlabs.com/Tests/images/taylor_avatar.png",
"user_last_active_epoch": 1544680026,
"user_creation_epoch": 1544713200,
"user_is_new": 1,
"user_token": "6dd4737a8b7ec61313ae5e900420d46815e1d13b2902be71b97a8fbf1f421a3e" }
Edit: This issue is resolved now. The issue was that I had to use a form tag to submit the fetch request. And I have to use FormData as the request option of the fetch request.

Promise doesn't reject [duplicate]

This question already has answers here:
How to handle HTTP code 4xx responses in fetch api
(4 answers)
Fetch: reject promise and catch the error if status is not OK?
(11 answers)
Closed 1 year ago.
Here is the code:
await fetch("http://localhost:3000/login", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
login: name,
password: pass
}),
})
.then(async() => {
await AsyncStorage.setItem('Login', name)
})
.catch(err => alert(err));
When I try to intentionally make a mistake in order to test the logging process, I get the error in the "Network" tab of my browser, but my website thinks that everything is fine and it executes the .then() code, even though it obviously shouldn't do that, because the Promise is rejected (it says POST http://localhost:3000/login 400 (Bad Request) in the console).
I tried a different code
.then(async () => {
await AsyncStorage.setItem('Login', name)
}, (reason) =>
alert(reason)
);
But it too doesn't work the way I want, it should execute this part (reason) => alert(reason)).
What's the solution?

How to catch the error when making fetch api request? [duplicate]

This question already has answers here:
How to handle HTTP code 4xx responses in fetch api
(4 answers)
Handle a 500 response with the fetch api
(2 answers)
try..catch not catching async/await errors
(1 answer)
Closed 2 years ago.
I am sending request with fetch api and make action according to the result is correct or it includes error.
my service code:
LoginUser(user: User) {
return fetch("http://localhost:8080/login", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify(user)
});
}
and my then-catch code which calls the above one is:
async loginUser() {
let response = await this._service.LoginUser(this.user)
.then(response => {return response.json()})
.then(response => {this._router.navigate(['/mainpage'])})
.catch(error => {alert(error)});
}
Whether the response is coming with code 500 Internal Server Error still it is redirecting to /mainpage and does not recognise the error. How can I fix this problem ?
When a fetch request comes back with an error code from the server, the catch of the promise is not executed, the then is. The catch is only executed if there is a network failure. See the fetch docs:
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.
What you need to do is, inside your then, check response.ok. If response.ok == false, then the request returned an error. You can find info about this error in response.status and response.statusText.
If you are using async await you shouldnt have to chain on .thens like you are resolving a promise.
I adjusted your code and wrapped it in a try/catch, the try/catch error will handle an error from a non response however you will need to check your server response for errors itself
async loginUser() {
try {
let response = await this._service.LoginUser(this.user)
// Check your response for error this may not be response.error
if (response.error) {
// Handle error
alert(error)
} else {
// Navigate on success
this._router.navigate(['/mainpage'])
}
} catch (err) {
alert(err)
}
}

How to avoid the CORS error without telling fetch "mode: "no-cors"? [duplicate]

This question already has answers here:
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 3 years ago.
My initial question (JavaScript fetch API data and use XML response as an object) was marked a duplicate of SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data using fetch, so I am asking another question, building on top of what I learned (or assume):
I have a cors error when using fetch() in JS to call an API if I don't define "{ mode: "no-cors" }". I also get the error when I run a local server! When I do define no-cors, I don't get the cors error, but the response seems to be empty.
How to avoid the cors error and get a response?
My code is the following:
async function apiCall() {
const url =
"https://service.runmyaccounts.com/api/latest/clients/apitest/invoices?api_key=d1bvbxkI8f1bnMBJ4sZiC-xupl4fOEzf"; // yes this is ok to publish as it is in the api documentation and just a test account
try {
const response = await fetch(url, {
headers: {
"Content-Type": "text/xml"
}
});
const data = await response.text();
console.log(data);
//return data;
} catch (err) {
console.log(err);
}
}
apiCall();
It seems to be hacked but... working: Using fetch with proxy
var proxy_url = 'https://cors-anywhere.herokuapp.com/';
var main_url = 'https://service.runmyaccounts.com/api/latest/clients/apitest/invoices?api_key=d1bvbxkI8f1bnMBJ4sZiC-xupl4fOEzf';
fetch(proxy_url + main_url)
.then(response => response.text())
.then(data => console.log(data));

Getting API response payload using fetch

I am using fetch to get the API response for GET and POST requests. When an error occurs, I am able to see the status code and the text i.e, 400 Bad Request. However, there is additional information being passed that explains why the error was thrown (i.e. username did not match). I can see this additional message in the response payload via Firefox developer tool's console but I am not sure how to get it via handling the fetch response.
Here's an example request:
fetch(url, {
method: 'POST',
body: JSON.stringify({
name: name,
description: description
}),
headers: {
"Content-type": "application/json; charset=UTF-8",
"Authorization": "Bearer " + token
}
}).then(response => {
if (!response.ok) {
throw Error(response.statusText)
}
return response
})
.catch(error => {
console.log(error)
})
Any ideas? Thanks.
Thank you everyone for your suggestions.
This tutorial helped me understand what to do.
https://css-tricks.com/using-fetch/
My problem was that when there is an error, the response is not JSON, it's text. So I needed to do something like this (taken from css-tricks.com):
fetch('https://api.github.com/users/chriscoyier/repos')
.then(response => response.text())
.then(data => {
console.log(data)
});
You seem to be passing only the statusText field of the response, which corresponds to the HTTP status code (And not the response body) - for example Bad Request for HTTP response code 400.
You can read the response body using one of the methods defined on the Response object returned by the fetch API. For example, if you're expecting a JSON response body, you can have:
const onSuccess = response => {
// Do something with the response
// What you return from here will go to the next .then
}
const onFailure = response => {
// response.json() returns a promise that resolves to the JSON sent in the body
// Note that whatever is returned from here will go to the next .then
// To go to the next .catch, you can throw from here
return response.json().then(jsonResponse => console.log(jsonResponse))
}
fetch(url, {
method: 'POST',
body: JSON.stringify({
name: name,
description: description
}),
headers: {
"Content-type": "application/json; charset=UTF-8",
"Authorization": "Bearer " + token
}
}).then(response => {
if (!response.ok) {
throw response
}
return response
})
.then(onSuccess, onFailure)
.catch(err => { /* Any error thrown from the handlers will be caught here */ })
You can have a look at the Response object documentation for more details.
Based off the docs, I'd do something more along the lines of this:
const response = await fetch('http://example.com/movies.json')
const myJson = await response.json();
console.log(JSON.stringify(myJson));
Otherwise you have to do everything inside of your .then().
In regards to the additional text you are looking for, that's totally dependent on the response object, and I have no way of knowing without seeing it.
#Voxum, your answer is missing important info, like a method..and ; await is good, but remember it should be in an async function, and you dont need to use it if you "thenify" .then() as that returns the promise. from the Fetch docs, that is their basic get/HTML example. i think the OP is asking for a API call for different types of methods, which will require a more advanced setup.
The thing is with a 400 response, the server is not giving you a response message as the 404 (for example) is telling you the page is not found. Usually the only time a server will give you a response message is when you get a good (success/200). there will usually be a message at response.json() or response.text() depending on your data coming back.
after you call fetch with the url, method and any headers use
.then((response) => {console.log(response.json());}); for json and use
.then((response) => {console.log(response.text());}); for xml/text
OP has the fetch set up properly but just needs to use response.json() or response.text(). again, a 200 response can still be a "incorrect password" and this is where you'll use this. don't expect a response body on the 400/500s. good luck!

Categories

Resources