feat(server): modularize backend and admin console
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import Request
|
||||
from fastapi import HTTPException
|
||||
|
||||
|
||||
PUBLIC_API_BASE_URL = os.getenv("PUBLIC_API_BASE_URL", "").strip().rstrip("/")
|
||||
VALID_CLIENT_TOKEN = os.getenv("CLIENT_API_TOKEN")
|
||||
RELEASE_MAIN_EXECUTABLE = os.getenv("RELEASE_MAIN_EXECUTABLE", "MainApp.exe").strip().replace(chr(92), "/").strip("/")
|
||||
TARGET_PLATFORM = os.getenv("TARGET_PLATFORM", "windows")
|
||||
TARGET_ARCH = os.getenv("TARGET_ARCH", "x64")
|
||||
PUBLISH_MAX_REQUEST_BYTES = int(os.getenv("PUBLISH_MAX_REQUEST_MB", "4096")) * 1024 * 1024
|
||||
PUBLISH_MAX_FILES = int(os.getenv("PUBLISH_MAX_FILES", "20000"))
|
||||
PUBLISH_MAX_FIELDS = int(os.getenv("PUBLISH_MAX_FIELDS", str(PUBLISH_MAX_FILES + 100)))
|
||||
|
||||
|
||||
def public_api_base_url(request: Request) -> str:
|
||||
if PUBLIC_API_BASE_URL:
|
||||
return PUBLIC_API_BASE_URL
|
||||
forwarded_proto = request.headers.get("x-forwarded-proto", "").split(",")[0].strip()
|
||||
forwarded_host = request.headers.get("x-forwarded-host", "").split(",")[0].strip()
|
||||
scheme = forwarded_proto or request.url.scheme
|
||||
host = forwarded_host or request.headers.get("host", "")
|
||||
if host:
|
||||
return f"{scheme}://{host}".rstrip("/")
|
||||
return str(request.base_url).rstrip("/")
|
||||
|
||||
|
||||
def default_client_main_executable() -> str:
|
||||
path = RELEASE_MAIN_EXECUTABLE.strip().replace(chr(92), "/").strip("/")
|
||||
if path.casefold().startswith("bin/"):
|
||||
path = path[4:]
|
||||
return path or "SimCAE.exe"
|
||||
|
||||
|
||||
def default_client_config_values(request: Request) -> dict:
|
||||
return {
|
||||
"api_base_url": public_api_base_url(request),
|
||||
"client_token": VALID_CLIENT_TOKEN or "",
|
||||
"launch_token": os.getenv("CLIENT_LAUNCH_TOKEN", "SimCAE_Launch_Token_2026_ChangeMe_32Bytes"),
|
||||
"request_timeout_ms": os.getenv("CLIENT_REQUEST_TIMEOUT_MS", "5000"),
|
||||
"temp_folder": os.getenv("CLIENT_TEMP_FOLDER", "update_temp"),
|
||||
"install_root": os.getenv("CLIENT_INSTALL_ROOT", ".."),
|
||||
"main_executable": os.getenv("CLIENT_MAIN_EXECUTABLE", default_client_main_executable()),
|
||||
"launcher_executable": os.getenv("CLIENT_LAUNCHER_EXECUTABLE", "Launcher.exe"),
|
||||
"updater_executable": os.getenv("CLIENT_UPDATER_EXECUTABLE", "Updater.exe"),
|
||||
"bootstrap_executable": os.getenv("CLIENT_BOOTSTRAP_EXECUTABLE", "Bootstrap.exe"),
|
||||
"health_check_timeout_ms": os.getenv("CLIENT_HEALTH_CHECK_TIMEOUT_MS", "15000"),
|
||||
"platform": TARGET_PLATFORM,
|
||||
"arch": TARGET_ARCH,
|
||||
}
|
||||
|
||||
|
||||
def normalize_executable_name(value: str) -> str:
|
||||
normalized = str(value or "").strip().replace(chr(92), "/").strip("/")
|
||||
if not normalized:
|
||||
return ""
|
||||
if normalized.startswith("/") or ":" in normalized or any(part in ("", ".", "..") for part in Path(normalized).parts):
|
||||
raise HTTPException(status_code=400, detail="主程序文件名必须是安全的相对路径")
|
||||
if not normalized.casefold().endswith(".exe"):
|
||||
normalized += ".exe"
|
||||
return normalized
|
||||
Reference in New Issue
Block a user