You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+PHP跨域报错:MissingAllowOriginHeader问题解决求助

React + PHP Todo应用CORS错误排查与修复

问题背景

使用React + PHP在XAMPP(Apache)环境开发Todo应用,相关代码如下:

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;
}

错误表现

尽管已添加header('Access-Control-Allow-Origin: *'),仍触发CORS错误:

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.

错误原因

  1. 请求格式不匹配:React端用JSON.stringify发送请求体,默认Content-Type为text/plain,但PHP的$_POST仅能解析application/x-www-form-urlencoded或multipart/form-data格式的数据,导致$_POST['action']不存在,代码报错,此时CORS头未正确发送。
  2. Header发送时机错误:数据库连接失败时,die()直接输出错误信息,可能在header()生效前就产生了输出,导致CORS头无法被浏览器识别。
  3. Apache配置缺失:未开启mod_headers模块,导致PHP的header()指令无法正常生效。
  4. 文件BOM头问题:PHP文件带有UTF-8 BOM头,会在代码执行前输出隐藏字符,阻断CORS头的发送。

修复方案

1. 修正请求格式与PHP数据解析

  • 修改React的fetch请求:添加Content-Type头,明确告知服务端请求体为JSON格式:
fetch(`${process.env.REACT_APP_ENDPOINT}`, {
  method: "POST",
  headers: {
    'Content-Type': 'application/json', // 新增
  },
  body: JSON.stringify({
    action: "todos",
  }),
})
  • 修改PHP获取数据的方式:读取原始请求体解析JSON数据,替代$_POST:
// 替换原有的 $action = $_POST['action'];
$input = json_decode(file_get_contents('php://input'), true);
$action = $input['action'] ?? '';

2. 确保CORS头正确发送

  • 扩展CORS头,覆盖必要的请求方法和头信息,并避免用die()直接终止程序:
<?php
// 先发送所有CORS相关头
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');

try {
    $db = new PDO("mysql:host=localhost;dbname=todo", "mustafa", "12345");
} catch (PDOException $e) {
    echo json_encode(['error' => $e->getMessage()]);
    exit; // 用exit替代die,确保头已发送
}

$input = json_decode(file_get_contents('php://input'), true);
$action = $input['action'] ?? '';

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

3. 开启Apache mod_headers模块

  • 打开XAMPP的Apache配置文件(httpd.conf),找到以下行并去掉前面的注释符#:
#LoadModule headers_module modules/mod_headers.so
  • 重启Apache服务。

4. 移除PHP文件的BOM头

  • 使用代码编辑器(如VSCode)将PHP文件保存为UTF-8无BOM格式:
    • VSCode:右下角编码选择UTF-8,点击后选择通过编码保存,再选UTF-8(无BOM)。

内容的提问来源于stack exchange,提问作者mbattaloglu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:57:17