Yii2中OPTIONS预检请求总是404,因框架默认不注册OPTIONS动作,路由匹配失败直接抛出NotFoundHttpException;需在behaviors()中前置自定义行为拦截,检查请求方法为OPTIONS时立即设置CORS响应头并调用end(204)退出。

Yii2中OPTIONS预检请求为什么总是404
因为Yii2默认不注册 OPTIONS 动作,路由匹配失败后直接抛出 NotFoundHttpException,浏览器收不到合法的CORS预检响应头,就判定跨域失败。这不是“没写actionOptions()”的问题,而是框架根本没走到控制器——连 beforeAction() 都不会触发。
用Behavior短路OPTIONS请求最稳
必须在MVC流程入口前拦截,避免鉴权、日志、模型加载等副作用。推荐在控制器的 behaviors() 中插入自定义行为:
- 检查
Yii::$app->request->getMethod() === 'OPTIONS' - 立即设置必需头:
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers - 调用
Yii::$app->end(204)强制退出,不走后续任何逻辑 - 这个行为必须放在鉴权类行为(如
AccessControl)之前,否则预检阶段就卡在权限检查里了
Cors::className()配置的两个坑
Cors 行为看似方便,但容易踩两个硬伤:
-
'Origin' => ['*']和'Credentials' => true同时启用 → 浏览器直接拒绝,连请求都不发 -
'Access-Control-Allow-Headers'没显式列出前端实际发送的头(比如X-Auth-Token)→ 预检失败,状态码仍是200但浏览器报错 - 它仍会进入控制器生命周期,若控制器里有
$this->user或$this->beforeAction()调用,预检时用户未登录就会崩
调试OPTIONS别靠F5刷页面
浏览器控制台看到的CORS错误太模糊,直接用curl测更准:
curl -I -X OPTIONS \ -H "Origin: https://example.com" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: X-Auth-Token,Content-Type" \ http://api.yourdomain.com/v1/users
重点看返回头里有没有 Access-Control-Allow-Origin、Access-Control-Allow-Headers,以及状态码是不是 204。如果返回 302 或 500,说明你还没拦住预检请求,它已经掉进重定向或异常流程里了。


















