开发实录

为什么我们重新设计了 WebSocket Mock DSL,而不是用 YAML、JSON 或 JS

轻量 Mock,不该先变重

HTTP 联调里,Mock 很轻:抓一帧,勾特征,改响应。一来一回就结束。

WebSocket 的轻量场景其实差不多短:连上、登录、回一句、隔几秒推个心跳。要 mock 的是一小段对话,不是一篇程序。

现成方案却常把这段对话塞进 JSON 规则表、YAML 配置、或一段 JS。功能很强,也能跑。 问题是:本来十来行能说完的事,要先填字段、堆括号、写 setInterval。轻量 Mock 先被容器写重了。

我们重新设计了一套 DSL,图的就是这件事——让轻量 Mock 更轻。界面叫 WS Flow,文件是 .dpws。人写剧本;JSON 只当编译产物。

同一段对话

「连上 challenge → 登录成功 → 每 15 秒 tick」,规则 JSON 常见是这样:

{
  "url": "wss://api.example.com/ws",
  "onOpen": [{ "send": { "type": "challenge" } }],
  "handlers": [
    {
      "match": { "type": "login" },
      "reply": { "type": "loginSuccess" },
      "then": {
        "every": "15s",
        "send": { "type": "tick" }
      }
    }
  ]
}

字花在 onOpenhandlersmatchreplythen 上。YAML 少了括号,壳还在:键、列表、再套一层,缩进既像配置又像对话。JS 最能打,一段 Mock 也容易变成小程序。

同一段,Flow 是这样:

# ws wss://api.example.com/ws
# profile type
# ping auto

--@open
    challenge

--login
    loginSuccess
        --@loop 15s
            tick

--@open 是连上,--login 是客户端登录,缩进里的是回什么、之后怎么推。loginSuccess 按文件头编成 {"type":"loginSuccess"},业务帧不必每次手写 JSON。延迟、周期推送写在行上(+300ms--@loop 15s),不必另起控制流。

语法就这些:缩进树,加少量符号(----@~scope|$+delay!close)。没有 if/for/函数。场景见 WebSocket Mock,符号见 .dpws 语言参考

HTTP Mock 仍从抓包、GUI 走;WS Flow 只服务这种短对话。两条不要揉成一张表。

轻的用 DSL,重的仍用 JS

Flow 只对准轻量 Mock:顺序的一小段会话。并发乱序、深分支、动态或随机 payload、要读外部数据——YAML/JSON 的生态(Schema、diff、CI)或直接写 JS 更合适。那不是 DSL 没写完,是我们不想把轻量语法撑成通用语言。

自研也有账:解析器、报错、高亮、补全都要自己养,同事要学新符号。校验已经接到编辑器,高亮和补全还早。换来的是:打开文件就像在读对话,而不是在读配置。

和前两篇是同一条线

抓包历史从 sql.js 迁到原生 SQLite,解决的是挂久了的存储。
桌面壳从 Electron 换成 Tauri,解决的是壳太重。
这篇是:轻量长连接 Mock 不该先被 JSON/YAML/JS 写重。我们用更短的 DSL,让它保持轻。

相关文档


欢迎 下载 DevPeek 看 HTTP Mock 与抓包怎么串;WS Flow 以 WebSocket Mock 文档 为准。不同看法可以到 GitHub Discussions 聊。