I have a basic react app communicating with a SQL database and have a demo API running with Flask. I know my API works with manual confirmation on Postman.
I am simply trying to post data to my database via my verified API. However, I run into issues with fetch based on the headers in my post method. Below is my current code:
const request = new Request("http://155.98.25.80:8000/user",
{method: 'POST',
headers:{'Content-Type': 'application/json', 'Access-Control-Allow-Origin': "http://localhost:3000/",
'Accept':'application/json'},
body: user_data,
mode:'cors',
});
console.log(request)
fetch(request)
.then(response => {
if (response.status === 200) {
return response.json();
}
else {
throw new Error('Something went wrong on api server!');
}
})
.then(response => {
console.debug(response);
// ...
}).catch(error => {
console.error(error);
});
}
It is a pretty standard POST request that is triggered on a button click. When I make this request, I can see the API returns a 200 code, meaning it went through to the database. However, in my browser (Chrome) console, I receive the following error: TypeError: Failed to fetch.
I am pretty lost here. I know my post request is going through, but it seems that the return is failing with the response. I have read many of the other posts dealing with this issue, and I am not sure what is going wrong with my app. Any help would be great.
I ran into this frustrating issue a few years ago and my have an answer for you. Your source of pain is probably the preflight check.
When you make a POST
request using postman it hits the POST
endpoint directly(POST http://155.98.25.80:8000/user
)
But when you make a POST
request through Chrome it first goes through a preflight check. This means that it first makes an OPTIONS
call to the same endpoint (OPTIONS http://155.98.25.80:8000/user
). The OPTIONS
call must return what is allowed on that endpoint(for CORS security). The OPTIONS
call must return headers that lets Chrome what kinds of requests it accepts and from whom.
For you, your OPTIONS http://155.98.25.80:8000/user
should return
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: *
Note: Access-Control-Allow-Origin
should be your specific api URL(maybe 155.98.25.80
), *
allows everything
Since Access-Control-Allow-Methods
allows POST
, POST
call will now be allowed when Chrome attempts it.
If you open Chrome Dev Tools and go to the Network tab you will see how before it makes a POST
call, it makes a OPTIONS
call
The OPTIONS
call returns the Access-Control
headers
Then, the POST
call can be made
Chrome does the preflight check on its own, you don't have to add any additional react code to make this happen.
Create a new endpoint (OPTIONS http://155.98.25.80:8000/user
) in Flask API that returns
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: *