- apis/source(.ivm).ts → src/source(.ivm).ts(音源属服务端职责,不入 SDK) - 新增 src/source-simple.ts:sources/*.mjs 进程内直载(getMusicUrl 极简契约), 与 *.js 的 IVM 沙箱(globalThis.lx 契约)按扩展名混排候选链,失败降权冷却 - server 挂载决策:SOURCE_ENABLED 非 0/false 启用,/url 取流分流到外部音源; 音源模式下登录态不参与取流,自动续期不启动(手动 /login/refresh 仍可用) - 新增 src/env.ts(.env 最先加载)与 test/source-simple-test.ts(并入 pnpm test)
3.0 KiB
3.0 KiB
外部聚合音源 —— isolated-vm 加载器
架构
调用方 ── source.kw.getMusicUrl(songInfo, type) ──▶ src/source.ts(懒加载候选链)
│
▼
src/source-ivm.ts
isolated-vm 硬隔离沙箱
┌──────────────────────────┐
│ 音源脚本(升版即换文件) │
│ ↕ 仅经显式桥接通道 │
└──────────────────────────┘
http(白名单) crypto zlib 定时器 console
- 接口契约与其它平台适配器一致:
getMusicUrl(songInfo, type) → { promise, cancelHttp },resolve →{ type, url } - 脚本来源:默认自动读取
sources/目录下按文件名排序的第一个.js;也可用SOURCE_SCRIPT_PATH显式指定 - 脚本升版:替换
sources/目录下的脚本文件即可,无需改代码 - 脚本文件含第三方混淆内容,不入库(
.gitignore已排除sources/)
安全模型
| 面 | 措施 |
|---|---|
| 进程 | isolate 无 process/require/fs,内存上限 256MB(可调) |
| HTTP | 默认阻止;白名单取脚本头部 SERVER_SCRIPT_CONFIG.apiUrl 同源,可覆盖 |
| 密钥 | crypto 桥接日志只记操作与长度,不落密钥内容 |
| 观测 | 每个音源 API 调用(on/send/request/utils/dispatch)均有日志,请求含耗时与状态码 |
HTTP 白名单选项(createIvmSource):
allowedOrigins: string[]—— 显式指定白名单(覆盖脚本声明)httpFilter: (url) => boolean—— 自定义判定,优先于 origin 白名单allowAllHttp: true—— 全部放行(仅调试用)
被拦截的请求会以错误回调返回脚本(✋ 日志标记),脚本按请求失败自行处理。
启用方式
设置环境变量 SOURCE_ENABLED(任意非 0/false 值)后启动服务器,取流请求即走音源;
不设置或为空则使用内置直连接口。歌词、封面、榜单等其余能力始终走内置实现。
环境变量(经 source.js 封装)
SOURCE_ENABLED=1—— 启用音源(见上)SOURCE_SCRIPT_PATH—— 脚本文件路径(缺省扫描sources/目录)SOURCE_LOG=0—— 关闭日志SOURCE_ALLOW_ALL_HTTP=1—— 放行全部 HTTP(调试用)
已知边界
- 音源请求回调的 resp 不含
raw/bytes(Buffer 无法跨隔离边界,实测脚本未使用) formData选项不支持(底层 httpFetch 不支持 multipart)updateAlert事件仅记日志,不弹窗- 沙箱内全局对象名
lx为第三方脚本依赖的 API 契约名,不可改名(见source-ivm.jsGLUE 注释)