webman跨域失败主因是cors插件未注册中间件、nginx未透传options预检请求、或credentials与origin=*冲突;需手动在middleware.php中注册corsmiddleware,nginx配置if处理options,并确保origin与credentials匹配。

Webman 的跨域问题,不能只靠 webman/cors 插件就完事——它默认不生效,且必须配合 Nginx 配置或手动加头,否则浏览器照样拦截。
为什么装了 webman/cors 还是跨域失败
因为该插件只是「提供了一套中间件」,但不会自动注册到全局中间件链里。你执行 composer require webman/cors 后,CorsMiddleware 类确实存在,但没被任何路由或控制器调用,等于没启用。
- 插件本身不修改
config/middleware.php,需手动添加 - 它只对匹配的路由生效(比如你只给
/api/*加了中间件,/data就不受控) - 若用了 Nginx 反向代理,而 Nginx 没透传 OPTIONS 请求,预检请求直接 404 或 502,插件根本收不到
必须在 config/middleware.php 中注册中间件
打开 config/middleware.php,把 webman/cors 的中间件加进全局或分组中间件里:
return [
'default' => [
// 其他中间件...
\Webman\Cors\CorsMiddleware::class,
],
];
如果你只想对 API 路由启用,改用分组方式更安全:
return [
'api' => [
\Webman\Cors\CorsMiddleware::class,
// 其他 API 相关中间件
]
];
然后在路由定义中指定中间件组:
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
Route::any('/api/data', [app\controller\IndexController::class, 'data'])->middleware('api');
- 别漏掉
->middleware('api'),否则中间件不触发 - 确保
CorsMiddleware在其他可能提前返回的中间件(如鉴权、日志)之后注册,否则头可能被覆盖
Nginx 层必须放行 OPTIONS 预检请求
浏览器发复杂请求(如带 Content-Type: application/json 或自定义 header)前,会先发一个 OPTIONS 请求。如果 Nginx 没配好,这个请求根本到不了 Webman,直接被 Nginx 拦截或返回 405。
在你的 Nginx server 块里,加这段配置(放在 location ^~ / 内):
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization;
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain; charset=utf-8';
add_header Content-Length 0;
return 204;
}
- 这段必须写在
location块内,不能只写在 server 级 -
add_header不支持嵌套 if,所以不能只靠 Webman 返回头来覆盖 Nginx 默认行为 - 若需支持
credentials(如 Cookie),Access-Control-Allow-Origin不能为*,得写具体域名,并加add_header Access-Control-Allow-Credentials true;
手动加响应头比依赖插件更可控
当插件行为不符合预期(比如 Origin 白名单校验太死、无法动态判断来源),直接在控制器里加头最稳妥:
public function data()
{
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$allowed = ['https://your-frontend.com', 'http://localhost:3000'];
if (in_array($origin, $allowed)) {
header('Access-Control-Allow-Origin: ' . $origin);
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
}
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
exit;
}
return json(['code' => 200, 'data' => 'Hello World']);
}
-
header()必须在任何输出之前调用,包括空格、BOM、echo -
OPTIONS请求要提前exit,否则后续逻辑还会执行 - 这种写法绕过中间件生命周期,适合调试或临时修复
真正卡住 Webman 跨域的,往往不是插件有没有,而是 Nginx 拦了 OPTIONS、中间件没注册、或者 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 冲突——这三个点漏一个,前端控制台就会继续报错。










