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

跨域场景下PHP如何向JavaScript Fetch API返回响应?

跨域POST请求下PHP无法返回响应的解决方法

问题核心原因

  1. 客户端设置mode: 'no-cors',该模式会限制浏览器读取响应内容,即便后端正常返回数据;
  2. 后端未配置跨域资源共享(CORS)响应头,跨域请求被浏览器拦截;
  3. 后端else分支仅设置状态码,未返回JSON格式响应,客户端无法解析;
  4. 客户端发送JSON格式数据,但PHP用$_POST接收(仅支持application/x-www-form-urlencoded或multipart/form-data格式),导致数据解析异常。

一、修正客户端Fetch代码

移除mode: 'no-cors',并确保请求体为JSON字符串:

fetch(this.url, {
    method: 'POST',
    body: JSON.stringify(this.getFormValues()),
    headers: {
        "Accept": "application/json",
        'Content-Type': 'application/json'
    }
})
.then(resp => {
    if (!resp.ok) throw new Error(resp.statusText);
    return resp.json();
})
.then(data => {
    console.log(data);
    if (data.ok) this.Metrics.setSent();
})
.then(() => {
    this.Metrics.setSent();
    this.Metrics.dismiss();
})
.catch(error => {
    console.log("错误: ", error);
    this.Metrics.dismiss();
});

二、修正PHP后端代码

添加CORS头、正确解析JSON请求体、确保所有分支返回JSON响应,并修复SQL注入风险:

<?php
include_once('database/connection.php');
// 配置CORS响应头,生产环境建议替换*为具体允许的域名
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type, Accept');
header('Content-Type: application/json');

// 解析JSON格式请求体
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'status' => 400, 'message' => '无效的JSON数据']);
    exit;
}

// 提取请求参数,添加默认值避免未定义索引错误
$ip = $input["ip"] ?? '';
$city = $input["city"] ?? '';
$state = $input["state"] ?? '';
$country = $input["country"] ?? '';
$category = $input["category"] ?? '';

// 使用预处理语句查询IP是否已注册,防止SQL注入
$ip_query = "SELECT * FROM registers WHERE `ip` = ?";
$stmt = mysqli_prepare($conn, $ip_query);
mysqli_stmt_bind_param($stmt, 's', $ip);
mysqli_stmt_execute($stmt);
$ip_result = mysqli_stmt_get_result($stmt);
$ip_check = mysqli_fetch_assoc($ip_result);

if (!$ip_check) {
    // 预处理语句插入新数据
    $new_query = "INSERT INTO `registers` (`ip`, `city`, `state`, `country`, `category`, `created`) VALUES (?, ?, ?, ?, ?, '2022-07-21 00:00:01')";
    $stmt = mysqli_prepare($conn, $new_query);
    mysqli_stmt_bind_param($stmt, 'sssss', $ip, $city, $state, $country, $category);
    $new_create = mysqli_stmt_execute($stmt);
    
    // 根据插入结果返回响应
    if ($new_create) {
        $response = ['ok' => true, 'status' => 200, 'message' => '注册成功'];
        http_response_code(200);
    } else {
        $response = ['ok' => false, 'status' => 500, 'message' => '注册失败'];
        http_response_code(500);
    }
    echo json_encode($response);
} else {
    // IP已注册时返回JSON响应,用409表示资源冲突更合理
    http_response_code(409);
    echo json_encode(['ok' => false, 'status' => 409, 'message' => '该IP已注册']);
}

关键修改说明

  • 移除mode: 'no-cors':该模式仅适用于无需处理响应的场景,会屏蔽浏览器对响应内容的读取权限;
  • JSON字符串转换:客户端需将表单对象转为JSON字符串,确保后端能正确解析;
  • 解析JSON请求体:PHP通过php://input读取原始请求数据,再解析为数组;
  • CORS头配置:服务器明确允许跨域请求,避免浏览器拦截响应;
  • 全分支JSON响应:无论成功或失败,都返回标准JSON格式,保证客户端可正常解析;
  • 预处理语句:彻底避免SQL注入风险,提升代码安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:16:04