简体   繁体   中英

REACT + PHP - blocked my CORS policy only in POST request

Overview
My react app is hosted on githup-pages and a PHP API is hosted on a standard, paid hosting.

This works (GET)
When I started developping my app, I encountered a pretty popular error, which is Access to fetch at... has been blocked by CORS policy . I have found a quick-fix which was to write this header("Access-Control-Allow-Origin: *") in the PHP's first lines and it worked . However those were the GET requests .

This doesn't work (POST)
This time I have a piece of code in which I have to use a POST request and need to access it's response. This is the piece of code responsible for sending the post request:

const editEvent = async () => {
    const requestOptions = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', },
        body: JSON.stringify({ eventID: chosenEvent, courseID: courseID, groupID: groupID, time:time, date: date, description: description, typeID: typeID, password: password}),
        mode: 'cors',
    };
    const response = await fetch(`https://aleksanderblaszkiewicz.pl/kiedykolos/edit_event.php`, requestOptions);
}

It happened again - I am getting same error Access to fetch at... has been blocked by CORS policy . Solution which I am using now is to use mode: 'no cors' but it doesn't let me to get the response as it is opaque. Another solution I have found is to add more headers:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Accept, Authorization, X-Requested-With, X-Auth-Token, Origin, Application");

But it doesn't work as well. Any sugestions? Full error code:

Access to fetch at 'https://aleksanderblaszkiewicz.pl/kiedykolos/add_event.php' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Full php code:

header("Access-Control-Allow-Origin: http://localhost:3000");
header("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Accept, Authorization, X-Requested-With, X-Auth-Token, Origin, Application");
$servername = "...";
$username = "...";
$password = "...";
$dbname = "...";

$connection = new mysqli($servername, $username, $password, $dbname);
mysqli_set_charset($connection, 'utf8'); 

if ($connection -> connect_errno) {
  echo "Failed to connect to MySQL: " . $connection -> connect_error;
  exit();
}

$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);

$courseID = $input["courseID"];
$groupID = $input["groupID"];
$date = $input["date"];
$time = $input["time"];
$description = $input["description"];
$typeID = $input["typeID"];
$password = $input["password"];

$sql = "INSERT 
        INTO `events` (`id`, `date`, `time`, `description`, `course_fk`, `year_group_fk`, `type_fk`)
        VALUES (NULL, '$date', '$time', '$description', '$courseID', '$groupID', '$typeID')";

if($password == "Ujebale321!") {
  $result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
  echo "Success";
}
else {
  echo "Wrong password";
}


mysqli_close($connection);
?>

The issue is that your server set a number of allowed headers that are not part of the origin request . The only request header in your Fetch object is content-type: application/json , so must match the Access-Control-Allow-Headers in you server.

The Access-Control-Request-Headers header is used when issuing a preflight request to let the server know what HTTP headers will be used when the actual request is made (such as with setRequestHeader()). This browser side header will be answered by the complementary server side header of Access-Control-Allow-Headers.

Source Mozilla

This is a potential solution that will make your CORS request work:

  // In your code, this function is never called...
  const editEvent = async () => {
        const requestOptions = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', },
            body: JSON.stringify({ eventID: chosenEvent, courseID: courseID, groupID: groupID, time:time, date: date, description: description, typeID: typeID, password: password}),
        };
        await fetch(`https://aleksanderblaszkiewicz.pl/kiedykolos/edit_event.php`, requestOptions)
          .then(response => console.log(JSON.stringify(response)))
          .catch(error => console.log(error))


    }

This is a pre-flight request because the content-type is application/json. This means the browser make a "pre-request" to the server to see if the request can be executed (and the response be sent).

Thus, in your server-side code, you can only use:

   header("Access-Control-Allow-Origin: http://localhost:3000");

Or:

   header("Access-Control-Allow-Origin: *");

If you want to include another response header beside the Access-Control-Allow-Origin, allow just the content-type header, which is the one you set in your origin Fetch request:

   header("Access-Control-Allow-Headers: Content-Type");

Add these lines in your php file and while calling the api in React JS use Axios instead of Fetch

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header("HTTP/1.1 200 OK");
die();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM