frankenphp需手动设置cors响应头并在入口文件拦截options预检请求;必须校验origin白名单、设置精确匹配的access-control-allow-origin、显式声明allow-credentials、allow-methods等头,并确保header()调用早于任何输出。

FrankenPHP 本身不内置 CORS 中间件,但作为基于 Swoole 的 PHP 运行时,它完全支持在 PHP 层手动设置响应头——而且必须这么做,因为浏览器的跨域拦截发生在响应阶段,关键在于响应头是否正确、及时、完整。
在入口脚本或框架路由前统一加响应头
FrankenPHP 没有传统 Apache/Nginx 的 .htaccess 或 header 指令,所有响应头必须由 PHP 输出。推荐在项目入口文件(如 public/index.php)最顶部、任何输出之前插入以下逻辑:
- 先读取
$_SERVER['HTTP_ORIGIN'],做白名单校验(禁用*配 credentials) - 对合法 Origin 设置
Access-Control-Allow-Origin(值必须与请求头 Origin 完全一致) - 显式设置
Access-Control-Allow-Credentials: true(如前端带 Cookie 或 Authorization) - 设置
Access-Control-Allow-Methods和Access-Control-Allow-Headers,覆盖实际用到的方法和头字段 - 加上
Vary: Origin防止 CDN 或代理缓存污染
必须拦截并正确响应 OPTIONS 预检请求
浏览器对非简单请求(如 POST + JSON、PUT、自定义 X-Token 头)会先发 OPTIONS。FrankenPHP 不会自动处理它,PHP 必须主动拦截:
- 在入口文件开头加判断:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; } - 确保这个判断在框架初始化、路由解析、数据库连接等任何可能输出之前执行
- 不要只写
exit,必须用http_response_code(204)返回无内容成功状态 - 预检响应也需携带
Access-Control-Allow-Origin、Allow-Methods、Allow-Headers等头,否则浏览器拒绝后续请求
注意 FrankenPHP 特有的运行约束
FrankenPHP 使用 Swoole 事件循环,部分传统 PHP 行为不适用:
-
header()函数可用,但必须在响应体开始输出前调用;一旦 echo、var_dump 或框架自动输出 HTML,就无法再设头 - 不能依赖
ob_start()后期补头——Swoole 响应流是即时的,缓冲控制不如 FPM 灵活 - 若用 Laravel/Symfony/ThinkPHP 等框架,优先使用其原生中间件机制(如 Laravel 的 CorsMiddleware),而非在控制器里零散写 header()
- 检查是否启用了 FrankenPHP 的静态文件服务(如 /public 目录直出);静态资源不走 PHP,无法设 CORS 头,需通过
frankenphp.yaml配置headers字段补充
调试与验证要点
跨域失败常因细节错位导致静默失败,建议逐项确认:
- 打开浏览器 Network 面板,看 OPTIONS 请求是否返回 204,响应头是否含
Allow-Origin和Allow-Methods - 主请求响应头中
Access-Control-Allow-Origin的值是否与请求头Origin完全一致(协议+域名+端口,区分大小写,无尾部斜杠) - 若前端用了
credentials: 'include',后端Allow-Origin绝不能是*,且必须有Allow-Credentials: true - 用 curl 模拟请求验证:
curl -H "Origin: https://your-frontend.com" -I https://your-api.com/api/test,观察响应头
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











