修复:server.py

This commit is contained in:
LIghtJUNction
2026-03-21 00:28:56 +08:00
parent 92b3e2d260
commit c238880cd2
2 changed files with 63 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ import hashlib
import logging
import os
import platform
import re
import socket
from collections.abc import Callable
from datetime import datetime
@@ -65,6 +66,9 @@ _BUNDLED_DIST = Path(__file__).parent / "dist"
APP: Quart
_ENV_PLACEHOLDER_RE = re.compile(
r"\$(?:\{(?P<braced>[A-Za-z_][A-Za-z0-9_]*)(?::-(?P<default>[^}]*))?\}|(?P<plain>[A-Za-z_][A-Za-z0-9_]*))"
)
def _parse_env_bool(value: str | None, default: bool) -> bool:
@@ -73,6 +77,39 @@ def _parse_env_bool(value: str | None, default: bool) -> bool:
return value.strip().lower() in {"1", "true", "yes", "on"}
def _expand_env_placeholders(value: str, field_name: str) -> str:
missing_vars: list[str] = []
def _replace(match: re.Match[str]) -> str:
var_name = match.group("braced") or match.group("plain")
default = match.group("default")
env_value = os.environ.get(var_name)
if env_value is not None:
return env_value
if default is not None:
return default
missing_vars.append(var_name)
return match.group(0)
expanded = _ENV_PLACEHOLDER_RE.sub(_replace, value)
if missing_vars:
missing = ", ".join(sorted(set(missing_vars)))
raise ValueError(
f"Unresolved environment variable(s) in dashboard {field_name}: {missing}"
)
return expanded
def _resolve_dashboard_value(
value: str | int | None,
*,
field_name: str,
) -> str | int | None:
if not isinstance(value, str):
return value
return _expand_env_placeholders(value, field_name).strip()
class AstrBotJSONProvider(DefaultJSONProvider):
def default(self, obj):
if isinstance(obj, datetime):
@@ -431,16 +468,22 @@ class AstrBotDashboard:
)
dashboard_config = self.config.get("dashboard", {})
host = (
host_value = (
os.environ.get("ASTRBOT_HOST")
or os.environ.get("DASHBOARD_HOST")
or dashboard_config.get("host", "0.0.0.0")
)
port = int(
host = _resolve_dashboard_value(host_value, field_name="host")
if not isinstance(host, str) or not host:
raise ValueError("Dashboard host must be a non-empty string")
port_value = (
os.environ.get("ASTRBOT_PORT")
or os.environ.get("DASHBOARD_PORT")
or dashboard_config.get("port", 6185)
)
resolved_port = _resolve_dashboard_value(port_value, field_name="port")
port = int(resolved_port)
ssl_config = dashboard_config.get("ssl", {})
ssl_enable = _parse_env_bool(
os.environ.get("ASTRBOT_SSL_ENABLE")
@@ -484,16 +527,19 @@ class AstrBotDashboard:
or os.environ.get("DASHBOARD_SSL_CERT")
or ssl_config.get("cert_file", "")
)
cert_file = _resolve_dashboard_value(cert_file, field_name="ssl.cert_file")
key_file = (
os.environ.get("ASTRBOT_SSL_KEY")
or os.environ.get("DASHBOARD_SSL_KEY")
or ssl_config.get("key_file", "")
)
key_file = _resolve_dashboard_value(key_file, field_name="ssl.key_file")
ca_certs = (
os.environ.get("ASTRBOT_SSL_CA_CERTS")
or os.environ.get("DASHBOARD_SSL_CA_CERTS")
or ssl_config.get("ca_certs", "")
)
ca_certs = _resolve_dashboard_value(ca_certs, field_name="ssl.ca_certs")
if cert_file and key_file:
cert_path = await anyio.Path(cert_file).expanduser()

View File

@@ -22,7 +22,7 @@ from astrbot.core.star.star import star_registry
from astrbot.core.star.star_handler import star_handlers_registry
from astrbot.core.utils.pip_installer import PipInstallError
from astrbot.dashboard.routes.plugin import PluginRoute
from astrbot.dashboard.server import AstrBotDashboard
from astrbot.dashboard.server import AstrBotDashboard, _expand_env_placeholders
from tests.fixtures.helpers import (
MockPluginBuilder,
create_mock_updater_install,
@@ -80,6 +80,20 @@ def test_check_port_in_use_ignores_permission_errors(monkeypatch: pytest.MonkeyP
assert server.check_port_in_use("127.0.0.1", 3002) is False
def test_expand_env_placeholders_resolves_env_and_default(
monkeypatch: pytest.MonkeyPatch,
):
monkeypatch.setenv("HOST", "0.0.0.0")
assert _expand_env_placeholders("${HOST}", "host") == "0.0.0.0"
assert _expand_env_placeholders("${MISSING:-3002}", "port") == "3002"
def test_expand_env_placeholders_raises_for_unresolved_variable():
with pytest.raises(ValueError, match="dashboard host: HOST"):
_expand_env_placeholders("${HOST}", "host")
@pytest_asyncio.fixture(scope="module")
async def core_lifecycle_td(tmp_path_factory):
"""Creates and initializes a core lifecycle instance with a temporary database."""