diff --git a/src/data/config.ts b/src/data/config.ts index c1a67a5..12bf70f 100755 --- a/src/data/config.ts +++ b/src/data/config.ts @@ -13,7 +13,15 @@ export interface BotConfig { adminGroups: number[]; autoReturnDelay: number; autoPauseOnEmpty: boolean; - idleTimeoutMinutes: number; + idleTimeoutMinutes: number; + // Public base URL used when generating share links (e.g. the bot专属链接). + // Leave empty to use the browser's current origin. Example: + // "https://music.example.com" or "http://1.2.3.4:3000" + publicUrl: string; + // When true, Express trusts X-Forwarded-* headers from a reverse proxy + // (nginx/Caddy/Cloudflare). Required for correct protocol/host detection + // behind HTTPS-terminating proxies. + trustProxy: boolean; } export function getDefaultConfig(): BotConfig { @@ -30,6 +38,8 @@ export function getDefaultConfig(): BotConfig { autoReturnDelay: 300, autoPauseOnEmpty: true, idleTimeoutMinutes: 0, + publicUrl: "", + trustProxy: false, }; } diff --git a/src/index.ts b/src/index.ts index 2f75fd6..9a056a9 100755 --- a/src/index.ts +++ b/src/index.ts @@ -79,7 +79,10 @@ async function main() { await webServer.start(); logger.info({ webPort: config.webPort }, "TSMusicBot started"); - logger.info(`WebUI: http://localhost:${config.webPort}`); + const publicUrl = (config.publicUrl ?? "").trim().replace(/\/+$/, ""); + logger.info( + `WebUI: ${publicUrl || `http://localhost:${config.webPort}`}` + ); const shutdown = () => { logger.info("Shutting down..."); diff --git a/src/web/server.ts b/src/web/server.ts index cb6d85d..90b7dec 100755 --- a/src/web/server.ts +++ b/src/web/server.ts @@ -38,8 +38,18 @@ export function createWebServer(options: WebServerOptions): WebServer { const server = http.createServer(app); const logger = options.logger.child({ component: "web" }); + if (options.config.trustProxy) { + // Honor X-Forwarded-* from a reverse proxy (nginx/Caddy/Cloudflare). + app.set("trust proxy", true); + } + app.use(express.json()); + app.get("/api/config/public-url", (_req, res) => { + const raw = (options.config.publicUrl ?? "").trim(); + res.json({ publicUrl: raw ? raw.replace(/\/+$/, "") : null }); + }); + app.use( "/api/bot", createBotRouter(options.botManager, options.config, options.configPath, logger) diff --git a/web/src/components/Navbar.vue b/web/src/components/Navbar.vue index d6b577b..c095d5d 100644 --- a/web/src/components/Navbar.vue +++ b/web/src/components/Navbar.vue @@ -59,10 +59,30 @@ + +