限流、审计、跨域中间件在webman中必须分别解决原子性、协程安全、预检拦截问题,否则失效;限流需校准挂载位置、驱动与key设计,审计须在process内实时取字段并结构化输出json,跨域需用route::any或显式处理options并动态校验origin。

限流、审计、跨域三类中间件在 Webman 中不能“写完就挂”,必须分别解决原子性、协程安全、预检拦截这三个硬伤,否则上线即失效。
限流中间件为什么挂了也没用?
挂载位置错、驱动选错、key 设计错,三者任一出问题,限流就形同虚设。
- 全局挂载(
config/middleware.php中''键下)会统计/favicon.ico和静态资源,建议加白名单过滤或改用路由组中间件 - 用
webman/rate-limiter且版本 INCR + EXPIRE 非原子——两个并发请求可能同时读到 99,各自 +1 后变成 101,突破阈值 - 推荐直接上
tinywan/limit-traffic,它默认用 Lua 脚本封装操作,Redis 层面强原子;key 默认含{ip}:{route},但若走 Nginx 反代,$request->ip()是127.0.0.1,得换成$request->header('x-real-ip') - 配置里别只写
[100, 60],要确认单位:这里是“60 秒内最多 100 次”,不是分钟
审计中间件日志为什么全是空或乱码?
Webman 常驻内存,中间件实例复用,不手动控制生命周期,LoggerInterface 句柄一复用就崩,日志要么丢、要么串行、要么阻塞协程。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 不能在
__construct()里存$logger或初始化StreamHandler——它非协程安全,高并发下会写错文件或卡死 - 用户 ID、真实 IP、路由名这些字段必须在
process()内实时取:$request->getAttribute('route_name', 'unknown')、$request->header('x-user-id')、$request->header('x-real-ip') - 结构化输出必须是单行 JSON,字段名固定,例如:
{"event_type":"request","ip":"1.2.3.4","route":"/api/user","cost_ms":12.45};敏感字段如"token"要用preg_replace()脱敏后再 encode - 耗时必须用
microtime(true)算差值,不用date()——毫秒级不准,审计就失去意义
CORS 中间件为什么 OPTIONS 总 404?
不是头没加,是 OPTIONS 根本没进中间件——路由没匹配上,中间件压根不执行。
- 用
Route::post('/login', ...)时,浏览器发的 OPTIONS 请求不匹配任何路由,直接 404,CORS 头根本不会发出 - 必须用
Route::any('/login', ...)或显式注册Route::options('/login', ...),让预检请求能走到中间件层 - 中间件里不能只做
withHeader(),必须开头判断:if ($request->method() === 'OPTIONS') { return response('', 204); },否则$handler($request)还会继续执行控制器,浪费资源还可能报错 - 若前端带
credentials: 'include',Access-Control-Allow-Origin就不能写*,得从$request->header('origin')动态取值,并白名单校验,不匹配就不设这个 header
真正难的不是写中间件,是理解 Webman 的常驻内存模型如何改变变量生命周期、路由匹配时机如何决定中间件能否执行、Redis 原子性如何影响限流精度——这些点漏一个,线上就等于没加。










