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.
错误原因
- 请求格式不匹配:React端用
JSON.stringify发送请求体,默认Content-Type为text/plain,但PHP的$_POST仅能解析application/x-www-form-urlencoded或multipart/form-data格式的数据,导致$_POST['action']不存在,代码报错,此时CORS头未正确发送。 - Header发送时机错误:数据库连接失败时,
die()直接输出错误信息,可能在header()生效前就产生了输出,导致CORS头无法被浏览器识别。 - Apache配置缺失:未开启
mod_headers模块,导致PHP的header()指令无法正常生效。 - 文件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)。
- VSCode:右下角编码选择
内容的提问来源于stack exchange,提问作者mbattaloglu
相关产品推荐
相关产品推荐

