Webman处理跨域必须在中间件中统一设置CORS响应头并拦截OPTIONS预检请求,因常驻内存特性导致传统header()失效;需用withHeader()链式设置且动态校验Origin白名单。

Webman 默认不处理跨域,直接加 header() 会失效 —— 因为 Webman 是基于 Swoole 的常驻内存框架,响应头必须在中间件或事件中统一设置,不能像传统 PHP 那样在脚本开头写 header()。
Webman 中间件里设置 CORS 响应头
Webman 的跨域逻辑必须放在中间件(Middleware)中,且需在所有业务逻辑之前执行。否则 Access-Control-Allow-Origin 等头可能被覆盖或根本没机会输出。
- 新建中间件:
app/middleware/CorsMiddleware.php - 在
handle()方法中设置响应头,注意要调用$response->withHeader()而非header() - 必须返回修改后的
$response,否则无效 - 若允许携带 Cookie,需同时设置
Access-Control-Allow-Credentials: true和指定具体域名(不能用*)
public function handle($request, \Closure $next)
{
$response = $next($request);
return $response
->withHeader('Access-Control-Allow-Origin', 'https://your-frontend.com')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->withHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With')
->withHeader('Access-Control-Allow-Credentials', 'true');
}
正确处理 OPTIONS 预检请求
浏览器对非简单请求(如带 Authorization 头、PUT 方法)会先发一次 OPTIONS 请求。Webman 若未拦截并提前返回,后续业务逻辑仍会执行,导致重复处理或报错。
- 在中间件中判断请求方法是否为
OPTIONS,是则直接返回空响应 + 204 状态码 - 不能只
exit或return空值,否则 Webman 可能抛出异常或返回 500 - 推荐用
Response::create('', 204)显式构造预检响应
if ($request->getMethod() === 'OPTIONS') {
return Response::create('', 204)
->withHeader('Access-Control-Allow-Origin', 'https://your-frontend.com')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->withHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
}
动态白名单校验 Origin 的安全写法
硬编码单个域名不够灵活,但直接用 * 会破坏 credentials 支持。真实项目中建议从配置读取白名单,并严格比对 Origin 请求头。
立即学习“PHP免费学习笔记(深入)”;
-
Origin可能为空(如本地文件打开),需判空;也可能含端口(http://localhost:3000),必须完整匹配 - 不要用
parse_url()拆解再拼,容易漏掉协议或端口差异 - 配置里域名末尾不要带斜杠,比对前也别手动 trim 空格 —— Webman 的
$request->getHeaderLine('Origin')返回值是原始字符串 - 若匹配失败,不要输出任何 CORS 头,避免被利用做开放重定向探测
$origin = $request->getHeaderLine('Origin');
$allowed = config('app.cors_origins', ['https://prod.com', 'https://staging.com']);
if ($origin && in_array($origin, $allowed)) {
$response = $response->withHeader('Access-Control-Allow-Origin', $origin);
}
为什么 Nginx 层加 add_header 在 Webman 里不推荐
Webman 运行在 Swoole 上,通常直连客户端(不经过 Nginx),或者仅用 Nginx 做反向代理和 SSL 终结。此时 Nginx 的 add_header 不会自动透传给 Swoole 应用,更不会参与预检逻辑控制。
- 若你用 Nginx 反代 Webman,可在
location块里加add_header,但无法做Origin白名单校验 - 若 Webman 直连(如 Docker 内网暴露端口),Nginx 根本不介入,配置完全无效
- 混合部署时,Nginx 和 Webman 同时设 CORS 头,可能冲突(如一个设了
credentials,另一个没设)
真正可控、可调试、符合 Webman 生命周期的方式,只有中间件。



















