workerman无内置router,需手动实现路由:在onrequest中解析uri和method,用正则或前缀匹配路由表,按http方法和路径分发到对应处理器,并注意连接状态、静态资源处理及404响应。

Workerman 本身没有内置 Router,得自己搭
Workerman 是个异步 TCP/HTTP 服务器框架,它不提供类似 Laravel 或 Express 那样的声明式路由系统。你不能直接写 get('/user', ...) 就生效——所有请求默认都落到 onMessage(HTTP 场景下是 onRequest)里,路由逻辑必须手动实现。
这不是缺陷,而是设计取舍:Workerman 追求轻量和可控,把分发权交给你。所以“优雅实现”,核心是「结构清晰 + 匹配高效 + 易维护」,而不是套用 Web 框架那一套。
用正则 + 路由表是最常用也最可控的方式
别碰第三方“Workerman Router”包,多数只是简单封装,反而增加抽象层、隐藏匹配细节、难调试。直接用数组存路由规则,配合 preg_match 或 str_starts_with 判断,更透明也更稳。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- HTTP 场景下,在
onRequest回调中解析$request->uri()和$request->method() - 路由表建议用二维数组:
['GET' => [['pattern' => '/api/user/(\d+)', 'handler' => $callback], ...], 'POST' => [...]] - 匹配顺序很重要:长路径优先(比如
/api/users/123应比/api/users先试),否则可能被前缀截胡 - 避免在循环里反复
preg_match大量规则;如果路由超 20 条,可预编译正则或改用前缀树(但多数项目真没必要)
注意 Workerman 的协程与回调上下文陷阱
你在路由 handler 里写的闭包或方法,运行时不在原始请求生命周期内——尤其开了 Worker::$daemonize = true 或用了 Timer::add 延迟执行时,$connection 可能已关闭,$request 对象也可能被复用或释放。
- 务必在 handler 开头检查
if (!$connection->isConnected()) return; - 不要在异步回调里直接调用
$connection->send(),除非你确认连接还活着且没发过响应 - 如果 handler 里要查数据库或调远程 API,推荐用
AsyncTcpConnection或Swoole\Coroutine\Http\Client(需搭配workerman/sync-redis等协程友好客户端) -
$request是一次性对象,不能跨回调保存引用;需要参数就提前 extract 成变量,比如$id = $matches[1] ?? null;
静态资源和 404 处理容易被忽略
很多人只顾业务路由,忘了 favicon.ico、/static/、OPTIONS 预检这些真实请求会打进来。不显式处理,要么 404 泛滥,要么触发默认行为(比如返回整个 index.html)。
- 在路由表最末尾加一条兜底:匹配
^/(favicon\.ico|robots\.txt|manifest\.json)$,直接file_get_contents返回 - 对
/static/开头的 GET 请求,用realpath+file_exists校验路径,禁止目录遍历(严禁直接拼接$_SERVER['REQUEST_URI']) - 404 不要只 echo 文本,要设状态码:
$response->status(404)->header('Content-Type', 'text/plain')->end('Not Found'); - OPTIONS 请求建议统一返回 204,不走业务路由逻辑,避免无谓匹配
真正的难点不在怎么写路由,而在怎么让每条规则的边界足够干净、错误反馈足够及时、连接生命周期不被误判——这些地方一松懈,线上就出连接重置或空响应。










