I am trying to call a PHP API running on localhost:8000
from a React app running on localhost:3000
. After many tries I am still getting "CORS Preflight Did Not Succeed" error.
My API has following headers:
if (@$_SERVER['HTTP_ORIGIN']) {
header("Origin: http://localhost:8000");
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
}
I call the API with fetch like this (but it somehow sends empty request body):
let inputData:object = {email, password}
fetch("http://localhost:8000/data/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(inputData)
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
The strange thing is that the requests are working normally when sent directly from the browser devtools (2nd screenshot) or API clients like Insomnia:
CodePudding user response:
Your cors origin must be localhost:3000.
header("Origin: http://localhost:3000");
Because your frontend running on 3000.
Where the request comes from should be added as cors definition.
CodePudding user response:
Make sure you are not outputting anything in php
before returning the response to the frontend application. A simple echo "test";
or a print_r
, vardump
etc. can trigger this error.
Also, make sure there are no empty lines before the opening <?php
tags since they send a premature response to the frontend that may cause this error.
CodePudding user response:
Problem(s)
Your first screenshot indicates that the response to the preflight request has status code 404. However, a necessary condition for CORS preflight to succeed is an ok status (i.e. a status in the range 2xx). See the relevant section (3.2.3) of the Fetch standard:
A successful HTTP response, i.e., one where the server developer intends to share it, to a CORS request can use any status, as long as it includes the headers stated above with values matching up with the request.
A successful HTTP response to a CORS-preflight request is similar, except it is restricted to an ok status, e.g., 200 or 204.
(my emphasis)
Solution
Make sure your server responds with a 2xx status to preflight requests that are meant to succeed.
Additional remarks
- There is never a need to allow the
Origin
header, since it's set by the user agent. You can removeOrigin
from the value of theAccess-Control-Allow-Headers
response header. - Why you're setting an
Origin
header in the response is unclear...Origin
is a request header. You should be able to drop thatheader("Origin: http://localhost:8000");
line.