跳转至

WebSocket

有两个 WS 端点,面向不同场景。

对比

REST /ws(:22222) 核心 WS(--websocket-port :44444)
协议 JSON 帧(base64(body) FTAPI binary(44 字节帧头 + protobuf body)
用途 推送 only(server → client) 全双工(兼容 Futu SDK)
客户端 浏览器 / websocat / 脚本 Futu 官方 futu-api SDK(走 WS transport)
鉴权 握手 ?token=Authorization: Bearer
per-message scope v1.0+ 按 proto_id 查

REST /ws —— 推送 only

适合浏览器前端、轻量脚本。

// 浏览器(WebSocket API 不能设 header,所以用 ?token=)
const ws = new WebSocket('ws://localhost:22222/ws?token=fc_xxxx...')

ws.onmessage = (ev) => {
  const event = JSON.parse(ev.data)
  // event: { type: 'quote' | 'trade' | 'notify',
  //          proto_id, sec_key?, sub_type?, acc_id?, body_b64 }
  const body = atob(event.body_b64)  // protobuf 编码的字节
  // ... 解码 body
}

v0.9+:服务端按 client scope 过滤推送:

  • qot:read-only key → 只收 quote + notify,收不到 trade
  • qot:read + acc:read → 三类都收

核心 WS —— 全双工 binary

# 启动时开这个端口
./futu-opend --websocket-port 44444 --ws-keys-file keys.json

用 futu-api SDK 的 WebSocket transport,或者 tokio-tungstenite 之类的原生客户端。

握手:HTTP upgrade 时带 ?token=Authorization: Bearer。缺 qot:read scope → HTTP 403 + JSON error。

per-message scope gate(v1.0+):每条消息都会按 proto_id 查 scope,不够就丢弃不响应。客户端会表现为 "请求超时 / 订阅未生效"。

proto_id scope
1xxx 系统
3xxx 行情 + 订阅 qot:read
2005 / 2202 / 2205 / 2237 交易写 trade:real
2xxx 账户读 + 订阅 acc:read

故障排查

症状 原因
握手 401 Bearer / ?token 拼错 或 keys.json 里没这把 key
握手 403 scope 不够 qot:read
订阅成功但收不到推送 scope 够 qot:read 但不够 acc:read(trade 推送被过滤)
某些命令不响应 per-message scope 被拒(看 audit log)
key revoked key 被 remove-key + SIGHUP 了

审计 + 观测

  • 握手成功 / 失败都写 audit JSONL(iface=ws
  • 过滤掉的推送计 futu_ws_filtered_pushes_total{required_scope, key_id}
  • 握手鉴权事件计 futu_auth_events_total{iface="ws"}

详见 审计与可观察性