tp6接口options预检失败的根本原因是预检请求未被正确拦截响应:需在自定义中间件handle()开头添加if($request->isoptions()){return response('',204);},并显式设置access-control-allow-methods含options、access-control-allow-headers含content-type,中间件须注册于app/middleware.php靠前位置。

TP6 接口 OPTIONS 预检失败,根本原因是浏览器发来的预检请求没被正确响应——不是你漏写了 CORS 头,而是这个 OPTIONS 请求压根没走到能写头的地方,或者响应缺关键字段。
必须拦截 OPTIONS 请求并快速返回 204
TP6 默认不处理 OPTIONS 方法,请求可能直接 405 或 404,浏览器就终止后续 POST。中间件必须在早期识别并终止它:
- 在自定义中间件(如 app/middleware/CorsMiddleware.php)的 handle() 开头加判断:
if ($request->isOptions()) { return response('', 204); } - 不能只设 header 后继续执行
$next($request),那样会进控制器,而控制器通常不响应 OPTIONS - 返回 204 状态码最稳妥,避免 Content-Length 或 body 引发兼容问题
响应头必须显式包含 Content-Type 和 OPTIONS 方法
即使 OPTIONS 请求被拦截了,响应头若不匹配浏览器预期,依然会失败:
-
Access-Control-Allow-Methods 必须含
OPTIONS,例如:GET, POST, PUT, DELETE, OPTIONS -
Access-Control-Allow-Headers 必须含
Content-Type(前端发 JSON 就必带),建议一并加上Authorization, X-Requested-With - 这些头要通过
$response->header()设置,直接用header()函数在 TP6 中大概率无效
中间件注册位置和顺序很关键
中间件必须足够靠前,否则可能被 Session、Auth 等中间件拦截或覆盖:
- 在 app/middleware.php 全局中间件数组中,把
\app\middleware\CorsMiddleware::class放在第一位或至少早于SessionInit和权限类中间件 - 如果只对 API 路由跨域,优先用路由级配置:
Route::post('api/login', 'Api/Login@login')->allowCrossDomain();,更轻量且不易错 - 确认该路由属于 HTTP 类型(非 console/event),否则
allowCrossDomain()不生效
带 Cookie 或 Authorization 时 Origin 不能写 *
前端若设置了 withCredentials: true,后端 Access-Control-Allow-Origin 就不能是通配符 *:
- 开发阶段可设为
http://localhost:3000或具体域名数组 - 同时必须设置
Access-Control-Allow-Credentials: true - 这两个头必须成对出现,缺一即报错:"The value of the 'Access-Control-Allow-Origin' header... must not be the wildcard '*'"











