hostname 配置通过 setting.json / Web UI 更新时跳过 http:// 前缀自动补全
Author: ryanfeng2001Created May 22, 2026Updated Jun 5, 2026
Bug 描述
Config.__post_init__ 中有 hostname 自动补全 http:// 前缀的逻辑(config.py 第287-289行),但通过 setting.json 或 Web UI 保存配置时,走的是 Config.update_config() → setattr() → self.init() 路径,完全跳过了 __post_init__ 中的 hostname 校验。
结果:setting.json 中写 "hostname": "192.168.66.66" 时,程序运行时 hostname 仍为 192.168.66.66(无 http:// 前缀),导致 URL 拼接异常。
复现步骤
- Docker 部署 xiaomusic v0.5.6,配置文件挂载到
/app/conf - 通过 Web UI 设置 hostname 为
192.168.66.66(纯 IP,无http://前缀) - 重启容器,查看日志:
hostname='192.168.66.66'- TTS 播放 URL 拼接为
192.168.66.66:58090/music/xxx.mp3(缺少协议前缀)
期望行为
无论通过 setting.json、Web UI 还是环境变量设置 hostname,都应自动补全 http:// 前缀。
实际行为
update_config() 方法(第341-348行)直接 setattr 后调用 self.init(),未执行 hostname 校验逻辑。
根因分析
调用链:
- 启动时
__post_init__执行,hostname 被正确补全为http://192.168.66.66 - 随后
try_init_setting()读取 setting.json update_config_from_setting()→Config.update_config()→setattr(self, "hostname", "192.168.66.66")- 第3步覆盖了第1步的补全结果
update_config()只调用self.init(),不调用__post_init__
建议修复
将 hostname 补全逻辑从 __post_init__ 提取为一个独立方法,在 update_config() 中也调用:
def _normalize_hostname(self):
if self.hostname:
if not self.hostname.startswith(("http://", "https://")):
self.hostname = f"http://{self.hostname}"
def __post_init__(self):
if self.proxy:
validate_proxy(self.proxy)
self._normalize_hostname() # 替换原有逻辑
self.init()
...
def update_config(self, data):
type_hints = get_type_hints(self, globals(), locals())
for k, v in data.items():
converted_value = self.convert_value(k, v, type_hints)
if converted_value is not None:
setattr(self, k, converted_value)
self._normalize_hostname() # 新增
self.init()环境
- xiaomusic 版本:v0.5.6
- 部署方式:Docker(镜像
hanxi/xiaomusic,sha256:58ec49959ad8) - 设备:小爱音箱 Pro (LX06)
- 设置方式:Web UI 配置面板 → setting.json
Source: hanxi/xiaomusic