- 四端=ws×client / ws×server(原有,补语义注释)+ **http×client**(新增 http_client.go:
调 OneBot HTTP API、请求-响应、retcode 判成败、token 只走 Authorization 头)+
**http×server**(新增 http_server.go:监听 listen_addr 收上报、fail-closed 鉴权、10MiB 体上限)
- 配置面:适配器新增 transport / api_base_url / report_path(json tag 沿用既有口径);
env 兜底 CHANNEL_QQ_OBV11_{TRANSPORT,API_BASE_URL,REPORT_PATH};**默认值=现状**(ws+server)
- 出站分流:session.go 发送路径按 transport 走 WS 写帧或 HTTP POST(不改它则 HTTP 端无法出站)
- 端口豁免边界:http+server 沿用 AGENTS §9 已登记的同一豁免(design/13 §0 原文即含 HTTP server),
且 listen_addr 为空时报错、**绝不开端口**(与 ws 侧同名校验成对)
- 关键取舍(已上报):OneBot 的 HTTP 是「动作 + 上报」两半,mode 决定**哪一半必需**、
另一半给齐字段就一并启用 ⇒ 单个适配器即可「收上报 + 回消息」,四端仍各自可独立选择与测试
- 复核:build/vet 绿 + qq_obv11/cmd 包测试绿 + `-race` 干净;10 条新用例(HTTP 两端全部用本地
httptest 假 OneBot,未连真实 QQ);变异 3 条(伪造 retcode 成功 / 去掉上报鉴权门 / 默认值翻 http)已还原
- 未接:get_group_list(后续)、无 token 时放行(与既有 ws_server 一致,如需 fail-closed 请裁决)
62 lines
2.5 KiB
Go
62 lines
2.5 KiB
Go
package main
|
|
|
|
// 覆盖裁决 1.4 在组合根侧的落点:qq-obv11 的四个端所需配置项由 .env 兜底进适配器配置,
|
|
// 且默认值保持现状(transport=ws、mode=server),不改变已部署行为。
|
|
|
|
import "testing"
|
|
|
|
// TestChannelAccountsFromEnv_QQObv11FourEnds 验证 env 兜底把 transport / mode /
|
|
// listen_addr / remote_url / api_base_url / report_path 带进账号配置,并且默认口径不变。
|
|
func TestChannelAccountsFromEnv_QQObv11FourEnds(t *testing.T) {
|
|
for _, k := range []string{
|
|
"CHANNEL_QQ_OBV11_TRANSPORT", "CHANNEL_QQ_OBV11_MODE", "CHANNEL_QQ_OBV11_LISTEN_ADDR",
|
|
"CHANNEL_QQ_OBV11_REMOTE_URL", "CHANNEL_QQ_OBV11_API_BASE_URL", "CHANNEL_QQ_OBV11_REPORT_PATH",
|
|
} {
|
|
t.Setenv(k, "")
|
|
}
|
|
acct := qqObv11EnvAccount(t)
|
|
if acct["transport"] != "ws" || acct["mode"] != "server" {
|
|
t.Fatalf("defaults = transport:%v mode:%v, want ws/server", acct["transport"], acct["mode"])
|
|
}
|
|
|
|
t.Setenv("CHANNEL_QQ_OBV11_TRANSPORT", "http")
|
|
t.Setenv("CHANNEL_QQ_OBV11_MODE", "client")
|
|
t.Setenv("CHANNEL_QQ_OBV11_API_BASE_URL", "http://127.0.0.1:3000")
|
|
t.Setenv("CHANNEL_QQ_OBV11_REPORT_PATH", "/onebot/report")
|
|
|
|
list := channelAccountsFromEnv()["qq-obv11"]
|
|
if len(list) != 1 {
|
|
t.Fatalf("qq-obv11 env accounts = %d, want 1", len(list))
|
|
}
|
|
acct = list[0].Config
|
|
if acct["transport"] != "http" || acct["mode"] != "client" {
|
|
t.Errorf("transport/mode = %v/%v, want http/client", acct["transport"], acct["mode"])
|
|
}
|
|
if acct["api_base_url"] != "http://127.0.0.1:3000" || acct["report_path"] != "/onebot/report" {
|
|
t.Errorf("api_base_url/report_path = %v/%v, want the env values", acct["api_base_url"], acct["report_path"])
|
|
}
|
|
|
|
// 端到端一次:env 配置经 DecodeConfig 进适配器后,四个端的开关仍然在。
|
|
built, err := buildAccountAdapter("qq-obv11", list[0], testLog())
|
|
if err != nil {
|
|
t.Fatalf("buildAccountAdapter error: %v", err)
|
|
}
|
|
cfg := built.Config()
|
|
if cfg["transport"] != "http" || cfg["mode"] != "client" {
|
|
t.Errorf("adapter transport/mode = %v/%v, want http/client", cfg["transport"], cfg["mode"])
|
|
}
|
|
if cfg["apiBaseURL"] != "http://127.0.0.1:3000" || cfg["reportPath"] != "/onebot/report" {
|
|
t.Errorf("adapter apiBaseURL/reportPath = %v/%v, want the env values", cfg["apiBaseURL"], cfg["reportPath"])
|
|
}
|
|
}
|
|
|
|
// qqObv11EnvAccount 取出 env 兜底里合成的 qq-obv11 账号配置。
|
|
func qqObv11EnvAccount(t *testing.T) map[string]any {
|
|
t.Helper()
|
|
list := channelAccountsFromEnv()["qq-obv11"]
|
|
if len(list) != 1 {
|
|
t.Fatalf("qq-obv11 env accounts = %d, want 1", len(list))
|
|
}
|
|
return list[0].Config
|
|
}
|