Commit Graph

1 Commits

Author SHA1 Message Date
e0e2bf9e44 feat(appconfig): 配置文件解析与 flag/file/default 三级合并
新增 internal/appconfig:把「从配置文件启动」所需的解析、密钥展开和
优先级合并抽成可单测的包,避免这块逻辑散落在 main 里。

- 优先级严格为 显式 flag > 配置文件 > 内置默认值;「是否显式传入」由
  flag.Visit 判定,绝不拿解析后的值与默认值比较——Go 的 flag 会无条件
  把默认值写进变量,直接读变量就会让默认值压过配置文件。
- 字段覆盖现有全部 flag:addr/user/password/workdir/bin/frpc/peers/join_key
  (join_key 兼容 joinKey 写法)。
- 字符串字段支持 ${VAR} 与 file:/path 两种展开;环境变量未定义/为空、
  secrets 文件读不到都直接报错,不静默降级成空口令。$$ 转义字面量 $。
- 文件缺失返回 (nil,nil) 不算错误;JSON 非法、未知键(如把 password 拼成
  passwd)、尾部多余内容一律报错,交给调用方响亮退出——静默回落到
  admin/admin 才是真正的安全问题。以 "_" 开头的键作注释键忽略,
  示例配置因此可以内嵌说明。
- -peer 显式传入时整体替换文件里的 peers,而不是追加;-join-key 的内置
  默认来自 $W4F_JOIN_KEY,属于更具体的进程级覆盖,仍优先于文件。
- Values 实现 String()/Summary() 并对手令与 join-key 脱敏,即使误用
  %v 打印也不会泄漏。

回归测试覆盖上述每一条,其中 TestResolveFileBeatsFlagDefaults 专门守
「默认值压过配置文件」这个坑。
2026-10-23 09:12:19 +08:00