在cPanel服务器使用PHP获取JSON数据时遭遇403错误求助
问题排查:跨域请求403与JSON解析错误
场景复现
我在index.html中嵌入了以下JavaScript代码,用来调用/data.php获取JSON数据:
async function fetchCelebritiesData() { try { const response = await fetch('/data.php'); const data = await response.json(); return data; } catch (error) { console.error('Error fetching data:', error); return []; } }
对应的PHP文件负责校验请求来源域名,并读取data.json返回数据,代码如下:
<?php // 校验请求来源域名 $allowedOrigins = array("example.com", "www.example.com"); $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; // 获取请求中的HTTP_ORIGIN if (in_array($origin, $allowedOrigins)) { header("Access-Control-Allow-Origin: $origin"); } else { header("HTTP/1.1 403 Forbidden"); exit; } // 读取并输出JSON数据 $data = file_get_contents("data.json"); header("Content-Type: application/json"); echo $data; ?>
当前遇到的问题:
- 前端返回
403 Forbidden错误 - 控制台提示
SyntaxError: Unexpected end of JSON input - PHP日志显示
Undefined index: HTTP_ORIGIN - 已确认PHP、JSON文件及文件夹权限为644,无权限问题
问题原因分析
HTTP_ORIGIN未定义的触发场景- 当请求是同域请求时,浏览器不会发送
HTTP_ORIGIN请求头,导致$_SERVER['HTTP_ORIGIN']不存在,触发日志报错;同时空字符串不在允许的域名列表中,直接返回403。 - 本地开发环境(如
localhost或127.0.0.1)的请求,部分浏览器也不会携带HTTP_ORIGIN头。
- 当请求是同域请求时,浏览器不会发送
JSON解析错误的关联原因
PHP返回403状态码时,没有输出任何JSON内容,前端尝试解析空内容为JSON,自然触发Unexpected end of JSON input错误。
解决方案
方案1:兼容同域与本地开发请求
修改PHP代码,处理HTTP_ORIGIN不存在的情况,并补充本地开发域名到允许列表:
<?php $allowedOrigins = array("example.com", "www.example.com", "localhost", "127.0.0.1"); // 获取请求来源,兼容无ORIGIN头的情况 $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; // 同域请求直接允许;跨域请求校验域名 if (empty($origin) || in_array(parse_url($origin, PHP_URL_HOST), $allowedOrigins)) { // 同域时设置为当前请求的Host,跨域时用请求的Origin $allowOrigin = empty($origin) ? $_SERVER['HTTP_HOST'] : $origin; header("Access-Control-Allow-Origin: $allowOrigin"); } else { header("HTTP/1.1 403 Forbidden"); exit; } // 读取并输出JSON数据 $data = file_get_contents("data.json"); header("Content-Type: application/json"); echo $data; ?>
方案2:前端增加状态码校验
在JavaScript的fetch逻辑中,先判断响应状态是否正常,再解析JSON,避免空内容解析报错:
async function fetchCelebritiesData() { try { const response = await fetch('/data.php'); // 先检查响应状态码是否正常 if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('获取数据出错:', error); return []; } }
额外注意事项
- 本地开发时,确保
allowedOrigins包含localhost或127.0.0.1,否则本地请求会被拦截。 - 检查
data.json文件是否存在,且内容是合法的JSON格式,避免后续返回无效JSON。
内容的提问来源于stack exchange,提问作者Kcalpesh Ajugia
相关产品推荐
相关产品推荐

