跳转至

BroSDK SDK 参考

当前版本:v1.0.0.7  最后更新:2026-05-08 本文档是 BroSDK 的统一接入参考文档。 内容覆盖动态库接口与 Web API,以 brosdk.h 公开接口为准。 如有字段或行为的疑问,请以头文件 brosdk.h 为最终依据。

1. 概述

BroSDK 是一个使用 C/C++ 实现的浏览器环境管理 SDK,对外提供两种接入方式:

  • 动态库接口:直接加载 brosdk.dll / brosdk.so / brosdk.dylib,通过 brosdk.h 公开接口调用

  • Web API:初始化时开启本地 HTTP/WebSocket 服务,HTTP 发起请求,WebSocket 接收异步事件

两种方式共享同一套浏览器生命周期、环境管理和数据持久化实现,但异步结果的交付方式不同:

  • 动态库接口:函数返回值 + sdk_result_cb_t 回调

  • Web API:同步接口直接返回;异步接口先返回 ACK,最终结果通过 WebSocket 推送

2. 平台支持

平台 架构 动态库 状态 备注
Windows x64 brosdk.dll 正式支持 主力开发与测试平台
Linux x64 brosdk.so 正式支持 支持主流发行版
macOS arm64 / x64 brosdk.dylib 正式支持 arm64 为主要测试架构

3. 通用约定

3.1 JSON 与编码

  • 所有请求体均为 UTF-8 JSON

  • 所有返回体与通知体均为 UTF-8 JSON

  • 动态库接口中的 len 均为字节长度,不包含末尾 \0

3.2 内存管理

  • 动态库接口返回的 out_data,使用后必须调用 sdk_free()

  • 回调中的 data 指针只在当前回调有效,如需长期保存请立即复制

  • sdk_cookies_storage_cb_t 若要替换 Cookie 数据,*new_data 必须通过 sdk_malloc() 分配

3.3 返回值、reqId 与辅助判断

需区分“同步返回码”与“异步请求受理 ID”两类返回值:

数值范围 含义
0 CL_OK,同步成功
1 CL_DONE,异步任务已受理,返回值不含实际 reqId
> 100000 异步请求已受理,并直接返回实际 reqId
100 ~ 255 Warning,例如 CL_WBUSY
< 0 Error

辅助函数:

  • sdk_is_ok(code)

  • sdk_is_done(code)

  • sdk_is_reqid(code)

  • sdk_is_warn(code)

  • sdk_is_error(code)

  • sdk_error_name(code)

  • sdk_error_string(code)

  • sdk_event_name(evtid)

重要说明:

  • 当前异步动态库接口可能返回 CL_DONE,也可能直接返回 reqId

  • 对于 Web API 异步 ACK,顶层 reqId 也可能是 0,也可能是实际受理到的请求 ID

  • 业务接入时,应把“sdk_is_done(code) 或 sdk_is_reqid(code) 为真”都视为“异步任务已进入调度”

3.4 异步回调语义

sdk_result_cb_t 是动态库接入时统一的异步结果通道。

  • 回调第一个参数 code 是本次通知的粗粒度状态

  • reqIdtypeeventId 及业务字段以 JSON body 为准

  • 回调第一个参数不应用作稳定的 reqId 或 eventId

推荐做法:

  1. 解析 JSON body

  2. 优先根据顶层 type 路由

  3. 如需关联请求,使用顶层 reqId

  4. data.eventId 作为事件枚举补充字段使用

线程安全注意事项:

  • sdk_cookies_storage_cb_t 在 SDK 内部已串行化,不会并发调用

  • sdk_result_cb_t 不保证串行,同一回调可能在不同事件驱动时并发调用

  • 建议宿主侧在回调中加锁,或只做最小操作(如入队)后在业务线程消费

  • 无论哪种回调,禁止在回调中调用 SDK 阻塞/同步接口(如 sdk_initsdk_shutdown),否则可能导致死锁

3.5 同步响应 Envelope

BroSDK 直接生成的同步响应结构如下:

{
  "code": 0,
  "reqId": 1309318677,
  "type": "sdk-init-success",
  "msg": "ok",
  "data": {
    "eventId": 10111
  }
}
字段 类型 说明
code int SDK 返回码
reqId int SDK 请求 ID
type string 事件名称
msg string 可读状态描述
data object 接口专属数据

例外:

  • env/createenv/updateenv/pageenv/getinfoenv/destroy 为后端原始 JSON 透传

  • netdiag 返回 BroSDK 网络诊断原始 JSON,结构为 code/msg/ok/data,不额外包含 reqId/type

  • 上述接口不会额外套一层 BroSDK 自己的 envelope

3.6 异步 Web API ACK Envelope

异步 Web API 接口的 HTTP 响应返回的是“已受理 ACK”,不是最终结果:

{
  "code": 0,
  "reqId": 1677842284,
  "type": "browser-close",
  "msg": "accepted",
  "data": {
    "eventId": 20140,
    "accepted": true,
    "async": true,
    "dispatchCode": 1,
    "dispatchMsg": "done"
  }
}

注意事项:

  • reqId 可能为 0,也可能为实际异步请求 ID

  • ACK 只表示请求已经进入 SDK 调度器

  • 最终成功或失败,必须通过 WebSocket 获取

3.7 浏览器生命周期通知结构

浏览器打开 / 关闭相关通知使用统一结构:

{
  "code": 0,
  "reqId": 369488048,
  "type": "browser-open-success",
  "msg": "ok",
  "data": {
    "envId": "2041695386304778240",
    "status": 2,
    "statusName": "Started",
    "progress": 100,
    "remoteDebuggingPort": 65534,
    "cdpReady": true
  },
  "envList": [
    {
      "envId": "2041695386304778240",
      "status": 2,
      "statusName": "Started",
      "progress": 100,
      "cdpReady": true
    }
  ]
}

data 常见字段:

字段 类型 说明
envId string 环境 ID
status int 浏览器生命周期状态
statusName string 生命周期状态名称
progress int 当前进度百分比
remoteDebuggingPort int CDP 端口,若当前实例已开启
cdpReady bool CDP 是否已可用于业务逻辑

当前 statusName 可能出现:

  • Idle

  • Downloading

  • Preparing

  • Starting

  • Started

  • Stopping

  • Stopped

  • Destroyed

  • StartFailed

  • StopFailed

4. 代理字段与当前策略

4.1 字段口径

代理桥决策会综合环境绑定代理与本次打开浏览器参数。browser/open 请求体中只支持传入 forwardproxy 与 bridgeProxy 应在创建或更新环境时绑定。

字段 来源 说明
proxy 环境创建 / 更新阶段绑定 最终上游代理;不作为 browser/open 参数传入
forward browser/open 本次启动参数 显式前置跳板,优先级高于 bridgeProxy
bridgeProxy 环境创建 / 更新阶段绑定 备用前置跳板;不作为 browser/open 参数传入

推荐统一使用完整代理 URL:

  • socks5://host:port

  • socks5://user:pass@host:port

  • socks5h://user:pass@host:port

  • http://user:pass@host:port\

4.2 当前默认策略的四条决策规则

当前版本在每次浏览器启动前,会依次评估以下四条规则(按优先级从高到低):

优先级 条件 实际行为
1 环境绑定的 proxy 为空 不走业务代理,bridgeProxy 和 forward 同时清空
2 环境绑定的 proxy 有值 + 宿主机已具备出海能力(global=true 直接使用 proxy,忽略 bridgeProxy 和 forward
3 环境绑定的 proxy 有值 + global=false + browser/open 传入 forward 本地 bridge -> forward -> proxy -> 目标网站
4 环境绑定的 proxy 有值 + global=false + forward 为空 + 环境绑定的 bridgeProxy 有值 本地 bridge -> bridgeProxy -> proxy -> 目标网站

global 是 SDK 内部对宿主机出海能力的判断值,不是客户配置字段。

进入代理桥时,SDK 会为每个浏览器实例单独启动一个本地 loopback bridge,并向 Chromium 注入:

--proxy-server=socks5://127.0.0.1:{port}

关键约束:

  • forward 和 bridgeProxy 不会同时生效,当前不支持双跳前置链(即不存在 forward -> bridgeProxy -> proxy 这种路径)

  • browser/open 只支持传入 forwardproxy 和 bridgeProxy 请在创建或更新环境时绑定

4.3 当前默认策略的重要说明

当前实现的三项关键行为:

  1. forward 是 browser/open 可传字段,参与本次启动的代理桥决策

  2. 宿主机已具备出海能力(global=true)时,SDK 自动忽略 forward 和 bridgeProxy,仅使用 proxy

  3. proxy 为空时,SDK 不注入本地代理桥,同时清空 bridgeProxy 和 forward

注意事项:

  • proxy 为空时,浏览器回退至 Chromium 默认网络栈,是否走系统代理取决于 Chromium / 操作系统默认行为

  • 如需行为稳定可预期,请在创建或更新环境时显式绑定完整 proxy URL,勿依赖客户机器隐式系统代理配置

  • forward 与 bridgeProxy 互斥,不支持双跳前置链

4.4 故障与回退

当前实现中,如果代理桥启动失败:

  • SDK 会记录 browser-proxy-* 相关诊断日志

  • 浏览器仍然会继续启动

  • 但此时不会再使用 SDK 管理的本地代理桥

5. Web API 参考

5.1 启用方式

常见做法是在动态库 sdk_init 的初始化 JSON 中携带 port,一次完成 SDK 初始化并启用内嵌 Web API:

{
  "userSig": "your-user-sign",
  "port": 9527
}

兼容入口 sdk_init_webapi(port) 只用于先启动本地 Web API 服务;业务初始化仍需随后调用 POST /sdk/v1/init 并传入 userSig

初始化完成后:

  • Web API HTTP 地址:http://127.0.0.1:{port}

  • WebSocket 地址:ws://127.0.0.1:{port}/

  • HTTP 请求与 WebSocket 使用同一个本地 TCP 端口

port 的当前语义:

行为
不传 不启用内嵌 Web API
0 SDK 自动分配本机空闲端口,实际端口在初始化响应的 data.port 中返回
> 0 SDK 尝试监听 127.0.0.1:{port},端口不可用时返回 CL_EPORT_UNAVAILABLE

5.2 认证模型

内嵌 Web API 当前不依赖 Authorization Header。

当前模型如下:

  • /sdk/v1/init 在 JSON body 中携带 userSig

  • 后续 Web API 请求复用当前已初始化的 SDK 实例

  • /sdk/v1/token/update 在 JSON body 中刷新 userSig

5.3 WebSocket 使用说明

WebSocket 是 Web API 的异步事件通道。调用异步接口(browser/installbrowser/openbrowser/closetoken/update)时,HTTP 响应只返回受理 ACK;最终进度与结果通过 WebSocket 推送。

连接地址

ws://127.0.0.1:{port}/

当前实现不区分连接 path,/ 与任意子路径均可接受。

消息格式

  • 帧类型:UTF-8 JSON 文本帧

  • 结构与 sdk_result_cb_t 回调收到的 JSON 一致(参见 §3.5 / §3.7)

  • 常规 SDK 事件通常包含 type(事件名称)、code(返回码)和 reqId 字段;异常响应可能只在 data 中携带错误信息

请求与事件关联

HTTP ACK 中的 reqId > 0 时,可用于匹配后续 WebSocket 事件。若 reqId 为 0,不要依赖它做精确关联,应结合 typeenvId 和业务上下文判断事件归属。

连接生命周期

场景 行为
未启用 Web API 前 本地服务未启动,TCP 连接被拒绝
连接建立时已有浏览器运行 SDK 立即推送一次运行状态快照,可用于恢复 UI 显示
多个客户端并发连接 支持;所有 WebSocket 事件广播到全部已连接客户端
客户端断开 SDK 不缓冲断线期间的事件;重连后可再次收到运行状态快照
SDK shutdown SDK 主动关闭所有 WebSocket 连接

推荐接入顺序

  1. sdk_init 返回成功

  2. 建立 WebSocket 连接,准备接收事件(可能立即收到运行状态快照)

  3. 发送 HTTP 请求,例如 POST /sdk/v1/browser/open

  4. HTTP 响应返回 ACK,记录 reqId(若不为 0

  5. 通过 WebSocket 接收最终事件,如 browser-open-success 或 browser-open-failed

主动推送事件

以下事件由 SDK 主动推送,不需要客户端先发起请求:

事件 触发场景
sdk-token-expire-warning token 剩余有效期低于阈值
sdk-token-expired token 已过期
browser-close-success(含 closeOrigin 浏览器进程意外退出或被用户手动关闭

通过 WebSocket 发送请求

WebSocket 帧中可包含带 path 字段的请求体,SDK 会按异步任务调度处理。当前实现所有 WebSocket 请求均视为异步,不区分同步接口语义。接入侧建议统一使用“HTTP 请求 + WebSocket 监听”的模式,语义更清晰。

5.4 Web API 同步与异步接口

接口 HTTP 响应语义 是否需要 WebSocket
initinfobrowser/infonetdiag 返回本次调用结果 不需要
env/createenv/updateenv/pageenv/getinfoenv/destroy 返回后端原始结果 不需要
browser/installbrowser/openbrowser/closetoken/update 返回受理 ACK 需要,用于接收最终结果

5.5 POST /sdk/v1/init

同步初始化 SDK。

请求字段:

字段 类型 必填 说明
userSig string 后端签发的用户令牌
workDir string 工作目录根路径,实际运行目录会被解析为 workDir/appId
port integer 内嵌 Web API 端口;不传则不开启,传 0 自动分配空闲端口
sdkApiUrl string 覆盖 SDK 后端地址;不传则使用 SDK 内置默认地址
autoUpdateKernel bool 覆盖 SDK 后端配置的autoUpdateKernel参数
logoPath string 覆盖 SDK 后端配置用户图标资源,使用本地图标资源(绝对路径)
debug bool 开启开发者日志,默认 false
verbose bool 开启详细日志(输出更细粒度的内部事件),默认 false;生产环境建议关闭

成功响应示例:

{
  "code": 0,
  "reqId": 1309318677,
  "type": "sdk-init-success",
  "msg": "ok",
  "data": {
    "workDir": "C:/BroSDK/1234567890",
    "port": 9527,
    "eventId": 10111
  }
}

当前实现的重要限制:

  • sdk_init 在同一进程内是全局串行入口

  • 若已有初始化操作进行中,后续调用直接返回 CL_WBUSY

5.6 POST /sdk/v1/info

同步获取 SDK 运行信息。

请求体:

  • 推荐传空对象 {}

  • 空 body 也可

成功响应示例:

{
  "code": 0,
  "reqId": 123456789,
  "type": "sdk-info-success",
  "msg": "ok",
  "data": {
    "info": {
      "deviceId": "device_xxx",
      "version": "1.0.0.25",
      "startupTime": 1744123456789,
      "coresInfo": {},
      "netInfo": {},
      "workDir": "C:/BroSDK/1234567890",
      "tokenExpiresInS": 3600,
      "dataFullyManaged": true
    },
    "eventId": 10131
  }
}

data.info 常用字段:

字段 类型 说明
deviceId string 当前机器指纹
version string SDK 版本号
startupTime integer SDK 启动时间戳
coresInfo object 已加载浏览器核心信息
netInfo object 当前网络环境快照
workDir string 实际运行目录
tokenExpiresInS integer 当前 token 剩余有效秒数
dataFullyManaged bool true 为全托管,false 为半托管

5.7 POST /sdk/v1/netdiag

同步执行网络 / 代理诊断。适用于浏览器启动前验证 proxy 与跳板链路可达性;调用方直接获取诊断结果,无需等待 WebSocket 事件。

请求字段:

字段 类型 必填 说明
url string 需要探测的目标 URL
proxy string 最终上游代理;为空时按直连诊断
bridgeProxy string 诊断链路中的前置跳板;当前接口只读取该字段,不读取 forward

请求示例:

{
  "url": "https://example.com",
  "proxy": "socks5://target-proxy:5206",
  "bridgeProxy": "socks5://jump-proxy:31034"
}

成功响应示例:

{
  "code": 0,
  "msg": "ok",
  "ok": true,
  "data": {
    "request": {
      "url": "https://example.com",
      "proxy": "socks5://target-proxy:5206",
      "bridgeProxy": "socks5://jump-proxy:31034"
    },
    "chain": {
      "targetProxy": "socks5://target-proxy:5206",
      "jumpCount": 1
    },
    "started": true,
    "runningAfterStart": true,
    "listenPort": 62000,
    "error": "",
    "bridgeDiagnostics": {},
    "urlProbe": {},

    "events": [ ]

  }
}

bridgeDiagnosticsurlProbe 和 events[ ].diagnostics 是诊断明细,字段会随底层网络探测能力扩展;接入侧应优先判断顶层 ok/code/msg,再展示或记录明细。

5.8 POST /sdk/v1/browser/info

同步获取当前运行中的浏览器列表。

请求体:

  • SDK 层返回全部运行中环境,不支持请求体过滤

  • 建议传 {} 或空 body

成功响应示例:

{
  "code": 0,
  "reqId": 1191362648,
  "type": "browser-info-success",
  "msg": "ok",
  "data": {
    "envs": [
      {
        "envId": "2039469749536034816",
        "remoteDebuggingPort": 65534
      }
    ],
    "eventId": 20116
  }
}

5.9 POST /sdk/v1/browser/install

异步安装浏览器核心资源。请求会根据初始化凭证中的核心版本列表匹配可安装包,下载 / 安装完成后 SDK 会重新加载本地核心列表。

请求字段:

字段 类型 必填 说明
cores array 需要安装的浏览器核心列表

cores[ ].major | integer / string | 是 | 浏览器核心主版本号,例如 134 |

请求示例:

{
  "cores": [
    { "major": 134 }
  ]
}

即时 ACK 示例:

{
  "code": 0,
  "reqId": 0,
  "type": "browser-install",
  "msg": "accepted",
  "data": {
    "eventId": 20350,
    "accepted": true,
    "async": true,
    "dispatchCode": 1,
    "dispatchMsg": "done"
  }
}

最终异步事件:

  • browser-install

  • browser-install-progress

  • browser-install-success

  • browser-install-failed

5.10 POST /sdk/v1/browser/open

异步打开一个或多个浏览器环境。

顶层请求字段:

字段 类型 必填 说明
envs array 要打开的环境列表

envs[ ] 支持三种写法:

  • 直接传字符串环境 ID

  • 直接传数字环境 ID

  • 传对象,对象中包含 envId 和可选覆盖参数

envs[ ] 对象字段:

字段 类型 必填 说明
envId string / integer 环境 ID
forward string 本次启动使用的前置跳板,优先级高于环境绑定的 bridgeProxy
args array Chromium 兼容命令行参数,每项为完整 switch
urls array 启动后自动打开的 URL
extensions array 本次启动注入的扩展数据配置
cookies array 本次启动注入的 Cookie JSON 数组
yunConfig object 定制浏览器透传内容

browser/open 不支持通过请求体覆盖 proxy 或 bridgeProxy。这两个字段应在创建 / 更新环境时绑定,打开浏览器时 SDK 会从环境信息中读取。

args[ ] 仅描述 Chromium 兼容命令行参数,每项应是完整字符串,例如:

  • --no-first-run

  • --no-default-browser-check

  • --disable-web-security

  • --remote-allow-origins=*

  • --remote-debugging-port=0

extensions[ ] 对象字段:

字段 类型 必填 说明
name string 扩展名称
id string Chrome 扩展 ID
data object 传给扩展的键值数据;键和值均为字符串,具体编码由扩展约定

cookies[ ] 对象字段兼容浏览器 Cookie JSON:

字段 类型 必填 说明
domain string Cookie 域
name string Cookie 名称
value string Cookie 值
path string Cookie 路径,通常为 /
expirationDate number 过期时间,Unix 秒时间戳;会话 Cookie 可不传
hostOnly bool 是否仅主机匹配
httpOnly bool 是否 HttpOnly
sameSite string / null 可为 laxstrictno_restriction 或 null
secure bool 是否 Secure
session bool 是否会话 Cookie
storeId string / null Cookie store ID

yunConfig{} 对象字段:

在yunConfig JSON对象内容会平铺透传到定义版浏览器,例如 shop{}whitelist[]blacklist[] ...

字段 类型 必填 说明
shop object 咨询定制版浏览器厂商
whitelist array
blacklist array

请求示例:

{
    "envs": [
        {
            "envId": "2051156171976347648",
            "forward": "",
            "args": [
                "--no-first-run",
                "--no-default-browser-check",
                "--disable-web-security",
                "--remote-allow-origins=*",
                "--remote-debugging-port=0",
                "--custom-data=aHR0cHM6Ly9iYWlkdS5jb20=",
                "--x-base-data=mofangUrl=aHR0cHM6Ly9iYWlkdS5jb20="
            ],
            "urls": [
                "https://baidu.com",
                "https://bing.com",
                "https://myip.ipipv.com"
            ],
            "yunConfig": {
                "shop": {
                    "shopId": "cd9ff4d2e44746a5ab58b56c546dfcc6",
                    "name": "141",
                    "shortName": "27008",
                    "platform": "",
                    "serial": "27008"
                },
                "whitelist": [
                    "www.baidu.com"
                ],
                "blacklist": [
                    "www.cn.bing.com"
                ]
            },
            "extensions": [
                {
                    "name": "chrome-mv3",
                    "id": "jicbihcejeehghnlckloefbklclkkbei",
                    "data": {
                        "key1": "aGVsbG8=",
                        "key3": "5L2g5aW9",
                        "key2": "12345234634574568478asdfdgsdfg"
                    }
                },
                {
                    "name": "testExt2",
                    "id": "afgbmmdnakcefnkchckgelobigkbboci",
                    "data": {
                        "data1": "5Zyo5ZCX77yfCg==",
                        "ddataTest22345": "d2VsY29tZQo=",
                        "testData": "!@#%^@$#^#$%&#%^*$%^*$^&*%^&*"
                    }
                }
            ],
            "cookies": [
                {
                    "domain": "www.baidu.com",
                    "expirationDate": 1776502336,
                    "hostOnly": true,
                    "httpOnly": false,
                    "name": "BD_UPN",
                    "path": "/",
                    "sameSite": null,
                    "secure": false,
                    "session": false,
                    "storeId": null,
                    "value": "123134753"
                },
                {
                    "domain": ".baidu.com",
                    "expirationDate": 1805640689.802383,
                    "hostOnly": false,
                    "httpOnly": false,
                    "name": "BAIDUID",
                    "path": "/",
                    "sameSite": "no_restriction",
                    "secure": true,
                    "session": false,
                    "storeId": null,
                    "value": "7CC918200AED607C30178FC6F821F9D48:FG=1"
                }
            ]
        }
    ]
}

即时 ACK 示例:

{
  "code": 0,
  "reqId": 1594794915,
  "type": "browser-open",
  "msg": "accepted",
  "data": {
    "eventId": 20110,
    "accepted": true,
    "async": true,
    "dispatchCode": 1,
    "dispatchMsg": "done"
  }
}

最终异步事件:

  • browser-open

  • browser-open-success

  • browser-open-failed

关键语义:

browser-open-success 表示浏览器已完全启动且 CDP 就绪。 Cookie / Storage / 扩展 / 自动化逻辑应以此通知作为就绪信号。

whiteList / blackList 会随环境配置写入浏览器侧配置;具体命中策略由当前浏览器核心实现决定。extensions[ ].data 与 cookies[ ] 可能包含敏感数据,接入层应限制数组长度、条目长度和字段格式,并在日志中做脱敏处理。

5.11 POST /sdk/v1/browser/close

异步关闭一个或多个浏览器环境。

请求字段:

字段 类型 必填 说明
envs array 要关闭的环境列表

envs[ ] 支持:

  • 字符串环境 ID

  • 数字环境 ID

  • 仅包含 envId 的对象

即时 ACK 示例:

{
  "code": 0,
  "reqId": 1677842284,
  "type": "browser-close",
  "msg": "accepted",
  "data": {
    "eventId": 20140,
    "accepted": true,
    "async": true,
    "dispatchCode": 1,
    "dispatchMsg": "done"
  }
}

最终关闭成功示例:

{
  "code": 0,
  "reqId": 1107807335,
  "type": "browser-close-success",
  "msg": "ok",
  "data": {
    "envId": "2041415694746128384",
    "status": 4,
    "statusName": "Stopped",
    "progress": 100,
    "cdpReady": false
  },

  "envList": [ ]

}

如果浏览器是被用户手动关窗,或者进程在运行中自行退出,SDK 仍会发送 browser-close-success,但会在 data 中附带关闭原因:

{
  "code": 0,
  "reqId": 1107807335,
  "type": "browser-close-success",
  "msg": "ok",
  "data": {
    "envId": "2041415694746128384",
    "status": 4,
    "statusName": "Stopped",
    "progress": 100,
    "cdpReady": false,
    "closeReasonCode": 103,
    "closeReasonName": "WBRWPROCEXITED",
    "closeReasonMsg": "browser process exited unexpectedly",
    "closeOrigin": "process-exited"
  },

  "envList": [ ]

}

关键语义:

即时 ACK 只表示关闭任务已被受理。   只有收到 browser-close-success,才表示环境已关闭完成。

5.12 POST /sdk/v1/token/update

异步刷新 userSig

请求字段:

字段 类型 必填 说明
userSig string 新的用户令牌

即时 ACK 示例:

{
  "code": 0,
  "reqId": 1587620091,
  "type": "sdk-token-update",
  "msg": "accepted",
  "data": {
    "eventId": 10120,
    "accepted": true,
    "async": true,
    "dispatchCode": 1,
    "dispatchMsg": "done"
  }
}

5.13 POST /sdk/v1/env/create

同步创建环境。

当前行为:

  • 请求体直接转发到后端 env/create

  • 响应体直接返回后端原始 JSON

  • 不追加 BroSDK 自己的 envelope

参数与响应结构不在本文维护,请查阅环境后端对接文档中的 env/create 接口契约。

5.14 POST /sdk/v1/env/update

同步更新环境。

当前行为:

  • 请求体直接转发到后端 env/update

  • 响应体直接返回后端原始 JSON

参数与响应结构不在本文维护,请查阅环境后端对接文档中的 env/update 接口契约。

5.15 POST /sdk/v1/env/page

同步分页查询环境。

当前行为:

  • 请求体直接转发到后端 env/page

  • 响应体直接返回后端原始 JSON

参数与响应结构不在本文维护,请查阅环境后端对接文档中的 env/page 接口契约。

5.16 POST /sdk/v1/env/getinfo

同步获取单个环境的后端 getEnvInfo 结果。

当前行为:

  • 请求体直接转发到后端 getEnvInfo

  • 响应体直接返回后端原始 JSON

  • SDK 打开浏览器时也会基于该结果构造环境配置,因此这里返回的字段通常比分页列表更完整

请求字段:

字段 类型 必填 说明
envId string / integer 环境 ID
os string 当前系统标识,建议传 WindowsmacOS 或 Linux

请求示例:

{
  "envId": "2041695386304778240",
  "os": "Windows"
}

5.17 POST /sdk/v1/env/destroy

同步销毁环境。

当前行为:

  • 请求体直接转发到后端 env/destroy

  • 响应体直接返回后端原始 JSON

  • 注意:销毁环境不等于关闭浏览器。如果该环境的浏览器仍在运行,请先调用 browser/close 并等待 browser-close-success,再调用 env/destroy

参数与响应结构不在本文维护,请查阅环境后端对接文档中的 env/destroy 接口契约。

5.18 POST /sdk/v1/shutdown

同步停止 SDK。

当前行为:

  • 停止 SDK

  • 关闭内嵌 Web API 服务

  • 销毁当前单例

6. 动态库接口参考

头文件:

#include "brosdk.h"

6.1 核心类型

typedef void *sdk_handle_t;

不透明的 SDK 实例句柄。

typedef void(SDK_CALL *sdk_result_cb_t)(
    int32_t code,
    void *user_data,
    const char *data,
    size_t len);

动态库接口的统一异步结果回调。业务字段请以 JSON body 为准。

typedef void(SDK_CALL *sdk_cookies_storage_cb_t)(
    const char *data,
    size_t len,
    char **new_data,
    size_t *new_len,
    void *user_data);

Cookie 持久化前的拦截回调。

6.2 生命周期与信息接口

函数 模式 说明
sdk_register_result_cb 同步 注册全局异步回调
sdk_register_cookies_storage_cb 同步 注册 Cookie 拦截回调
sdk_init_cpp 同步 仅获取 SDK 句柄,不执行初始化
sdk_init 同步 初始化 SDK,返回堆分配的 JSON 响应
sdk_init_async 异步 受理后返回 CL_DONE 或实际 reqId
sdk_init_webapi 同步辅助函数 兼容入口,新接入建议直接在 sdk_init 中携带 "port"
sdk_info 同步 返回 SDK info JSON
sdk_network_diagnostics 同步 返回网络 / 代理诊断 JSON
sdk_browser_info 同步 返回当前运行中的浏览器列表 JSON
sdk_token_update 异步 刷新用户令牌
sdk_shutdown 同步 停止 SDK 并销毁单例

sdk_network_diagnostics 的请求体与 /sdk/v1/netdiag 一致,返回的 out_data 必须通过 sdk_free() 释放。

6.3 浏览器接口

函数 模式 说明
sdk_browser_install 异步 安装浏览器核心资源
sdk_browser_open 异步 最终 ready 信号是 browser-open-success
sdk_browser_close 异步 最终关闭完成信号是 browser-close-success

sdk_browser_install 的请求体与 /sdk/v1/browser/install 一致,必须包含 cores[ ].major。进度和最终结果通过 sdk_result_cb_t 回调返回。

6.4 环境接口

函数 模式 说明
sdk_env_create 同步 返回后端原始 JSON
sdk_env_update 同步 返回后端原始 JSON
sdk_env_page 同步 返回后端原始 JSON
sdk_env_getinfo 同步 返回后端 getEnvInfo 原始 JSON
sdk_env_destroy 同步 返回后端原始 JSON

sdk_env_getinfo 的请求体与 /sdk/v1/env/getinfo 一致,返回的 out_data 必须通过 sdk_free() 释放。C++ ISDK 虚接口提供 NetworkDiagnostics(...) 与 GetEnvInfo(...),语义与对应动态库接口一致。

sdk_register_cookies_storage_cb() 有三个接入细节需注意:

  • 回调接收的是明文 Cookie JSON 数组,而非最终落盘 / 上传的加密二进制

  • 若返回替换后的 JSON,SDK 将以该 JSON 继续执行后续加密与持久化

  • Cookie 快照为空时,SDK 也会规范化为 [ ] 后触发回调,不静默跳过

6.6 内存与辅助接口

SDK_API void *SDK_CALL sdk_malloc(size_t size);
SDK_API void  SDK_CALL sdk_free(void *ptr);

所有 SDK 返回的动态内存都应通过 sdk_free() 释放。

SDK_API const char *SDK_CALL sdk_error_name(int32_t code);
SDK_API const char *SDK_CALL sdk_error_string(int32_t code);
SDK_API const char *SDK_CALL sdk_event_name(int32_t evtid);

静态字符串辅助函数,返回值不能释放。

SDK_API bool SDK_CALL sdk_is_error(int32_t code);
SDK_API bool SDK_CALL sdk_is_warn(int32_t code);
SDK_API bool SDK_CALL sdk_is_reqid(int32_t code);
SDK_API bool SDK_CALL sdk_is_ok(int32_t code);
SDK_API bool SDK_CALL sdk_is_done(int32_t code);
SDK_API bool SDK_CALL sdk_is_event(int32_t code);

7.1 托管模式

可通过 sdk_info().dataFullyManaged 判断当前模式:

模式 说明
false 半托管 只落本地 SQLite,不做 OSS 同步
true 全托管 SQLite 作为本地缓存,同时后台同步 OSS

7.2 浏览器关闭时的持久化链路

当前实现中,浏览器关闭后的 Cookie 持久化链路如下:

  1. 从浏览器快照提取 Cookie JSON 数组

  2. 调用 sdk_cookies_storage_cb_t,允许宿主查看或替换明文 JSON

  3. 把最终 JSON 转成 Cookie protobuf

  4. 使用 BroEncryptCookiesWithDEK(appId, coKeyVer, coKey, dek) 加密 Cookie

  5. 将加密 envelope 再次打包为 protobuf,并做 br 压缩

  6. 立即写入本地 SQLite

  7. 若为全托管,再异步上传到 OSS

Storage 的链路不同:

  • Storage 不走 Cookie 这套 DEK 加密

  • 当前实现是按存储策略收集浏览器数据文件,打包后做 br 压缩

  • 本地 SQLite 与 OSS 持有的是同一份压缩归档

当前实现里,Cookie 在本地 SQLite 和 OSS 中都不是明文 JSON:

存储位置 实际内容
SQLite cookies 列 BroEncryptCookiesWithDEK 生成的加密 Cookie 包,再经 br 压缩后的二进制
OSS Cookie 对象 与本地 SQLite 相同的加密 Cookie 二进制

加密所依赖的关键材料来源:

字段 来源
appId SDK 当前应用上下文
coKey / coKeyVer SDK 初始化后的凭证信息
dek 当前环境 envInfo 中返回的 DEK

因此,客户如需接管 Cookie 明文,只能在 sdk_cookies_storage_cb_t 回调阶段处理;一旦进入持久化阶段,SDK 保存和上传的都是加密后的二进制。

7.4 当前 OSS 对象路径口径

当前代码实现不会要求客户自己拼接 Cookie / Storage 对象名:

  • 后端返回 cookieUpPath / storageUpPath 前缀

  • SDK 会自动去掉前导 /

  • 然后自动追加 {envId}-v1.br

因此:

  • 请勿在接入文档中硬编码旧版的 cookies.pb / storage.zst 路径模板

  • 业务如需记录对象路径,请以后端返回的元数据与 SDK 实际回填结果为准

7.5 全托管模式下的本地缓存仲裁

现在本地 SQLite 还会维护以下元数据:

  • sync_state

  • cookie_md5

  • storage_md5

  • cookie_file_url

  • storage_file_url

  • last_sync_ms

  • updated_ms

浏览器打开时,全托管模式下会按以下规则判断是否直接使用本地 SQLite:

  • sync_state = Dirty:说明本地刚关闭过、OSS 可能还未同步,优先使用本地

  • sync_state = UploadFailed:说明上次上传失败,优先使用本地

  • 后端远端元数据缺失:优先使用本地

  • 本地 md5 / fileUrl 与远端一致:优先使用本地

  • 其余情况:认为远端更新更可信,回退到 OSS 下载

全托管模式下,SDK 不盲目信任 SQLite 缓存,而是先做本地 / 远端元数据比对。

OSS 上传失败重试机制:

当全托管模式下 OSS 上传失败时,SDK 不会丢弃数据:

  • 本地 SQLite 中会保留 sync_state = UploadFailed 状态

  • 下次该环境的浏览器启动时,SDK 会检测到 UploadFailed 并在生命周期内自动重试上传

  • 重试时机:下次浏览器关闭后的持久化流程中

  • 因此,即使 OSS 暂时不可用,数据也不会丢失,仅会延迟同步

7.6 browser-close-success 与上传完成不是同一件事

当前实现中:

  • browser-close-success 表示本地快照已经完成、SQLite 已可用于下次启动

  • 它不表示 OSS 上传已经完成

  • 如果全托管上传失败,本地 SQLite 会保留 UploadFailed 状态,后续生命周期仍可重试

8. 集成时必须注意的规则

  • 先调用 sdk_register_result_cb(),再进入异步业务流程

  • 把 sdk_init 当成进程内全局串行入口

  • 对于异步动态库接口,返回 CL_DONE 或 reqId 都表示“请求已受理”

  • Web API 中 initinfobrowser/infonetdiag 与 env/* 为同步接口;browser/installbrowser/openbrowser/closetoken/update 为异步 ACK

  • Web API 的异步接口必须同时建立 WebSocket,用于接收最终结果

  • 浏览器可用的真正信号是 browser-open-success

  • 浏览器真正关闭完成的信号是 browser-close-success

  • browser-close-success 只保证本地持久化完成,不保证 OSS 上传完成

  • 如果浏览器是用户手动关闭或进程自行退出,仍可能上报 browser-close-success,但 data.closeReason* 会说明真实原因

  • env/* 接口和 init/info/browser/* 的回包包装方式不同,前者是后端原始 JSON 透传;netdiag 也是同步原始诊断 JSON

  • env/createenv/updateenv/pageenv/destroy 的请求参数与响应字段请以后端对接文档为准,SDK 文档不重复维护

  • 如需代理行为稳定可预期,请在创建 / 更新环境时绑定 proxy / bridgeProxy,并在 browser/open 中按需传入 forward;勿依赖客户机器隐式系统代理环境

  • netdiag 只读取 bridgeProxy 作为诊断跳板;如果要验证浏览器启动中的 forward 链路,请把同一个跳板值显式放到 bridgeProxy 里诊断

  • urlsargswhiteListblackListextensionscookies 这类数组字段建议由接入层做长度、条目格式和敏感值校验

9. 事件与错误码附录

常用事件码:

事件 ID 名称
10110 sdk-init
10111 sdk-init-success
10112 sdk-init-failed
10120 sdk-token-update
10121 sdk-token-update-success
10122 sdk-token-update-failed
10123 sdk-token-expire-warning
10124 sdk-token-expired
10130 sdk-info
10131 sdk-info-success
10132 sdk-info-failed
10140 sdk-netdiag
10141 sdk-netdiag-success
10142 sdk-netdiag-failed
20110 browser-open
20111 browser-open-success
20112 browser-open-failed
20115 browser-info
20116 browser-info-success
20117 browser-info-failed
20140 browser-close
20141 browser-close-success
20142 browser-close-failed
20210 browser-env-create
20211 browser-env-create-success
20212 browser-env-create-failed
20220 browser-env-update
20221 browser-env-update-success
20222 browser-env-update-failed
20230 browser-env-page
20231 browser-env-page-success
20232 browser-env-page-failed
20240 browser-env-destroy
20241 browser-env-destroy-success
20242 browser-env-destroy-failed
20250 browser-env-info
20251 browser-env-info-success
20252 browser-env-info-failed
20350 browser-install
20351 browser-install-progress
20352 browser-install-success
20353 browser-install-failed
20600 browser-proxy
20601 browser-proxy-success
20602 browser-proxy-failed
20603 browser-proxy-dns-resolve-failed
20604 browser-proxy-tcp-connect-failed
20605 browser-proxy-http-connect-rejected
20606 browser-proxy-socks5-auth-failed
20607 browser-proxy-socks5-connect-rejected
20608 browser-proxy-write-failed

常用错误 / 警告码:

代码 名称 说明
0 CL_OK 成功
1 CL_DONE 异步任务已受理
103 CL_WBRWPROCEXITED 浏览器进程自行退出;常见于手动关窗或运行中异常退出
104 CL_WBUSY 资源忙,另一个初始化操作正在进行
-3002 CL_ETIMEOUT 超时
-3003 CL_EINVALID 参数错误
-3005 CL_EALREADY 已存在或重复初始化;进程内 SDK 单例已运行,无需再次初始化
-3012 CL_ENOTINITIALIZED SDK 未初始化
-3019 CL_EPORT_UNAVAILABLE 端口非法或已占用
-3023 CL_EOSS_NOCLIENT OSS 客户端未初始化
-3024 CL_EOSS_DOWNLOAD OSS 下载失败
-3025 CL_EOSS_UPLOAD OSS 上传失败
-3028 CL_ECOOKIE_RESTORE Cookie 恢复失败
-3029 CL_ESTORAGE_RESTORE Storage 恢复失败
-3502 CL_EHTTP_POST 后端 HTTP 失败
-3509 CL_ETOKEN_INVALID Token 无效
-3511 CL_EWORKDIR_INVALID 工作目录无效
-3512 CL_ENETWORK 网络或代理诊断失败
-4000 及以下 CL_ESDKAPI 系列 后端 SDK API 错误

本文明确区分了 BroSDK 直接生成的响应结构与直接透传后端的 env 接口响应结构。 如接入侧同时依赖完整的后端环境模型,请以后端 env API 契约作为完整字段集合的最终依据。