React + PHP API 抛出 CORS 预检错误

React + PHP API throws CORS preflight error

我正在尝试从 localhost:3000 上的 React 应用 运行 在 localhost:8000 上调用 PHP API 运行。经过多次尝试后,我仍然收到“CORS 预检未成功”错误。

从 React 应用发送:

从开发工具发送:

我的 API 有以下 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');
} 

我用这样的 fetch 调用 API(但它以某种方式发送空请求 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)
})

奇怪的是,直接从浏览器开发工具(第二张截图)或 API Insomnia 等客户端发送请求时,请求工作正常:

你的 cors 来源必须是 localhost:3000。

header("来源:http://localhost:3000");

因为您的前端 运行 在 3000 上。

应将请求的来源添加为 cors 定义。

问题

您的第一个屏幕截图表明对预检请求的响应具有状态代码 404。但是,CORS 预检成功的必要条件是 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.

(我的重点)

解决方案

确保您的服务器以 2xx 状态响应本应成功的预检请求。


补充说明

  1. 从来没有必要允许 Origin header,因为它是由用户代理设置的。您可以从 Access-Control-Allow-Headers 响应 header.
  2. 的值中删除 Origin
  3. 为什么要在 响应 中设置 Origin header 不清楚... Origin is a request header。您应该能够删除 header("Origin: http://localhost:8000"); 行。
  4. 您应该考虑使用经过验证的 CORS 中间件,而不是“手动”实施 CORS(error-prone)。

在将响应返回给前端应用程序之前,请确保您没有在 php 中输出任何内容。一个简单的 echo "test";print_rvardump 等可以触发此错误。

此外,请确保在开始 <?php 标记之前没有空行,因为它们会向前端发送过早的响应,这可能会导致此错误。