#882·xiaomusic

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 拼接异常。

复现步骤

  1. Docker 部署 xiaomusic v0.5.6,配置文件挂载到 /app/conf
  2. 通过 Web UI 设置 hostname 为 192.168.66.66(纯 IP,无 http:// 前缀)
  3. 重启容器,查看日志:
hostname='192.168.66.66'
  1. TTS 播放 URL 拼接为 192.168.66.66:58090/music/xxx.mp3(缺少协议前缀)

期望行为

无论通过 setting.json、Web UI 还是环境变量设置 hostname,都应自动补全 http:// 前缀。

实际行为

update_config() 方法(第341-348行)直接 setattr 后调用 self.init(),未执行 hostname 校验逻辑。

根因分析

调用链:

  1. 启动时 __post_init__ 执行,hostname 被正确补全为 http://192.168.66.66
  2. 随后 try_init_setting() 读取 setting.json
  3. update_config_from_setting()Config.update_config()setattr(self, "hostname", "192.168.66.66")
  4. 第3步覆盖了第1步的补全结果
  5. update_config() 只调用 self.init(),不调用 __post_init__

建议修复

将 hostname 补全逻辑从 __post_init__ 提取为一个独立方法,在 update_config() 中也调用:

python
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