Search code examples
phpreactjscors

React and PHP - CORS Error: MissingAllowOriginHeader


I am developing a todo app to work with React and PHP for the first time. I am using Apache(XAMPP).

App.js:

import { useEffect, useState } from "react";

const App = () => {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    fetch(`${process.env.REACT_APP_ENDPOINT}`, {
      method: "POST",
      body: JSON.stringify({
        action: "todos",
      }),
    })
      .then((response) => response.json())
      .then((data) => setTodos(data));
  }, []);
  return (
    <div>
      <h1>Todo App</h1>
    </div>
  );
};

export default App;

index.php:

<?php
header('Access-Control-Allow-Origin: *');

try {
    $db = new PDO("mysql:host=localhost;dbname=todo", "mustafa", "12345");
} catch (PDOException $e) {
    die($e->getMessage());
}

$action = $_POST['action'];

switch ($action) {
    case 'todos':
        $query = $db->query("SELECT * FROM todos order by id desc")->fetchAll(PDO::FETCH_ASSOC);
        echo json_encode($query);
        break;
}

Although I have the header('Access-Control-Allow-Origin: *'), It throws me the MissingAllowOriginHeader error:

Access to fetch at 'http://localhost/react-php-backend' from origin 'http://localhost:3000' has been blocked by CORS policy: 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.

What is the reason that gives this error? How can I fix this? Because of that I cannot connect database.


Solution

  • In 2023, when almost all browsers requires strick origin policy you need to modify your headers, either in .htaccess

    <IfModule mod_headers.c>
       #Header set Access-Control-Allow-Origin "*"
       SetEnvIf Origin "http(s)?://(.+\.)?domain\.ext(:\d{1,5})?$" CORS=$0
       Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS
       Header merge  Vary "Origin"
       Header set Access-Control-Allow-Methods "GET, POST, PATCH, PUT, DELETE, OPTIONS"
       Header set Access-Control-Allow-Headers: "*"
       
    </IfModule>
    

    or inside php

    <?php
    function cors()
    {
        // for options, return imm.
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            // may also be using PUT, PATCH, HEAD etc
            {
                header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
            }
    
            if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
                header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
            }
    
            exit(0);
        }
    
        $origin = "*";
        if (isset($_REQUEST['origin'])) {
            $origin = $_REQUEST['origin'];
        }
    
        if (isset($_SERVER['origin'])) {
            $origin = $_SERVER['origin'];
        }
    
        if (isset($_SERVER['HTTP_REFERER'])) {
            $origin = $_SERVER['HTTP_REFERER'];
        }
    
        if (isset($_SERVER['HTTP_ORIGIN'])) {
            $origin = $_SERVER["HTTP_ORIGIN"];
        }
    
        // remove trailing / for origin
        $origin = rtrim($origin, "/");
    
        header("Access-Control-Allow-Origin: " . $origin, true);
        header("Access-Control-Allow-Headers: *", true);
        header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS, post, get', true);
        header('Access-Control-Allow-Credentials: true', true);
    }
    
    cors();
    

    tbh, both would be also ok...