fix(wallpaper): 配置回填加固,兼容缺失配置段与未替换占位符

新增 needFill 辅助函数统一判断某个配置项是否「等于没配」:
配置项不存在、值为空串、或仍是未被替换的 ${PLACEHOLDER} 三种情况。

背景:gf v2.10.2 起不再自动替换 ${ENV} 占位符,且容器内跑的
config.yaml 可能是旧版(没有 wallpaper 配置段)。原先只判断
是否含 "${" 会在「配置段整体缺失」时漏判,导致 wallpaper.root
与 wallpaper.baseUrl 拿不到兜底值。

adapter.Get 返回 any 而非 *gvar.Var,故取值统一走 gconv.String。
This commit is contained in:
夏犀麟 2026-09-14 02:04:32 +08:00
parent d0a084b80e
commit a337336a50

View File

@ -63,6 +63,20 @@ func setIfEmpty(adapter *gcfg.AdapterFile, key, envName string) {
} }
} }
// needFill 判断某个配置项是否「等于没配」:不存在、为空串、或仍是未被替换的
// ${PLACEHOLDER}。gf v2.10.2 起不再自动替换占位符,容器里跑的 config.yaml
// 也可能是旧版(没有对应的配置段),这两种情况都必须回填兜底值。
//
// 注意 adapter.Get 返回的是 any 而不是 *gvar.Var取值统一走 gconv。
func needFill(ctx context.Context, adapter *gcfg.AdapterFile, key string) bool {
v, err := adapter.Get(ctx, key)
if err != nil || v == nil {
return true
}
s := gconv.String(v)
return s == "" || gstr.Contains(s, "${")
}
// injectEnv 手动把关键环境变量写入配置系统。 // injectEnv 手动把关键环境变量写入配置系统。
// 注意gf v2.10.2 起配置不再自动替换 ${ENV} 占位符,需在此显式注入, // 注意gf v2.10.2 起配置不再自动替换 ${ENV} 占位符,需在此显式注入,
// 否则 config.dev.yaml 中的 ${DB_DSN}/${JWT_SECRET} 会原样传给数据库与 JWT。 // 否则 config.dev.yaml 中的 ${DB_DSN}/${JWT_SECRET} 会原样传给数据库与 JWT。
@ -86,17 +100,20 @@ func injectEnv(ctx context.Context) {
_ = adapter.Set("jwt.secret", devDefaultJWTSecret) _ = adapter.Set("jwt.secret", devDefaultJWTSecret)
} }
} }
// 壁纸库路径同理:占位符没被注入时要回填,否则会真的创建一个名为 // 壁纸库路径同理,但要处理**三种**缺失形态:配置项不存在(容器里跑的
// "${WALLPAPER_ROOT}" 的目录,图片全落到那里且难以察觉。 // config.yaml 可能是旧版、压根没有 wallpaper 段)、值为空、以及占位符
// 没被替换。任何一种漏掉都会掉进 NewStorage 的相对路径兜底
// (容器内 ./data/wallpaper表现为「上传成功但 nginx 找不到文件」,
// 而且重启容器就全丢 —— 这种故障极难排查,所以这里必须兜死。
// 生产兜底到 /data/www/wallpaper由 nginx 直出),开发兜底到仓库内 data/。 // 生产兜底到 /data/www/wallpaper由 nginx 直出),开发兜底到仓库内 data/。
if v, _ := adapter.Get(ctx, "wallpaper.root"); v != nil && gstr.Contains(gconv.String(v), "${") { if needFill(ctx, adapter, "wallpaper.root") {
if isProd { if isProd {
_ = adapter.Set("wallpaper.root", "/data/www/wallpaper") _ = adapter.Set("wallpaper.root", "/data/www/wallpaper")
} else { } else {
_ = adapter.Set("wallpaper.root", "./data/wallpaper") _ = adapter.Set("wallpaper.root", "./data/wallpaper")
} }
} }
if v, _ := adapter.Get(ctx, "wallpaper.baseUrl"); v != nil && gstr.Contains(gconv.String(v), "${") { if needFill(ctx, adapter, "wallpaper.baseUrl") {
if isProd { if isProd {
_ = adapter.Set("wallpaper.baseUrl", "https://xpcool.com/wallpaper") _ = adapter.Set("wallpaper.baseUrl", "https://xpcool.com/wallpaper")
} else { } else {