r002: Config-Port 3003→3013 (Port-Konflikt), robustes Fallback
- Config-Server wechselt auf 127.0.0.1:3013 (3003 war belegt) - Binary: Port belegt → Warnung + weiterlaufen (kein Crash) - mua.page: Config-Port 3013 - .txz neu gepackt, SHA256 aktualisiert
This commit is contained in:
+60
-50
@@ -296,66 +296,76 @@ const server = Bun.serve({
|
||||
},
|
||||
});
|
||||
|
||||
// ── Config-Server (nur localhost:127.0.0.1:3003) ───────────────────────
|
||||
// ── Config-Server (nur localhost:127.0.0.1:3013) ───────────────────────
|
||||
// Separater Server, nur von localhost erreichbar (WebGUI auf demselben Host).
|
||||
// Kein Header-Spoofing, kein File-Permission-Problem.
|
||||
const CONFIG_PORT = Number(process.env["MUA_CONFIG_PORT"] ?? 3003);
|
||||
const configServer = Bun.serve({
|
||||
port: CONFIG_PORT,
|
||||
hostname: "127.0.0.1", // nur localhost
|
||||
idleTimeout: 30,
|
||||
async fetch(req) {
|
||||
const url = new URL(req.url);
|
||||
const path = url.pathname;
|
||||
const method = req.method;
|
||||
// Wenn der Port belegt ist: Warnung + weiterlaufen (MCP-Server bleibt up).
|
||||
const CONFIG_PORT = Number(process.env["MUA_CONFIG_PORT"] ?? 3013);
|
||||
let configServer: ReturnType<typeof Bun.serve> | null = null;
|
||||
try {
|
||||
configServer = Bun.serve({
|
||||
port: CONFIG_PORT,
|
||||
hostname: "127.0.0.1", // nur localhost
|
||||
idleTimeout: 30,
|
||||
async fetch(req) {
|
||||
const url = new URL(req.url);
|
||||
const path = url.pathname;
|
||||
const method = req.method;
|
||||
|
||||
if (path !== "/config") {
|
||||
return Response.json({ error: "Not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
// GET: Config lesen
|
||||
if (method === "GET") {
|
||||
return Response.json({
|
||||
apiKey: getApiKey(),
|
||||
enabledTools: getEnabledTools(),
|
||||
allTools: TOOLS.map((t) => t.name),
|
||||
});
|
||||
}
|
||||
|
||||
// POST: Config schreiben
|
||||
if (method === "POST") {
|
||||
let body: Record<string, unknown>;
|
||||
try {
|
||||
body = JSON.parse(await req.text());
|
||||
} catch {
|
||||
return Response.json({ error: "Invalid JSON" }, { status: 400 });
|
||||
if (path !== "/config") {
|
||||
return Response.json({ error: "Not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
// "generate": neuen API-Key generieren
|
||||
if (body["generate"] === true) {
|
||||
setApiKey(randomBytes(32).toString("hex"));
|
||||
} else if (typeof body["apiKey"] === "string" && (body["apiKey"] as string).length > 0) {
|
||||
setApiKey(body["apiKey"] as string);
|
||||
}
|
||||
if (Array.isArray(body["enabledTools"])) {
|
||||
const tools = (body["enabledTools"] as unknown[])
|
||||
.filter((t): t is string => typeof t === "string");
|
||||
setEnabledTools(tools);
|
||||
// GET: Config lesen
|
||||
if (method === "GET") {
|
||||
return Response.json({
|
||||
apiKey: getApiKey(),
|
||||
enabledTools: getEnabledTools(),
|
||||
allTools: TOOLS.map((t) => t.name),
|
||||
});
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
ok: true,
|
||||
apiKey: getApiKey(),
|
||||
enabledTools: getEnabledTools(),
|
||||
});
|
||||
}
|
||||
// POST: Config schreiben
|
||||
if (method === "POST") {
|
||||
let body: Record<string, unknown>;
|
||||
try {
|
||||
body = JSON.parse(await req.text());
|
||||
} catch {
|
||||
return Response.json({ error: "Invalid JSON" }, { status: 400 });
|
||||
}
|
||||
|
||||
return Response.json({ error: "Method not allowed" }, { status: 405 });
|
||||
},
|
||||
});
|
||||
// "generate": neuen API-Key generieren
|
||||
if (body["generate"] === true) {
|
||||
setApiKey(randomBytes(32).toString("hex"));
|
||||
} else if (typeof body["apiKey"] === "string" && (body["apiKey"] as string).length > 0) {
|
||||
setApiKey(body["apiKey"] as string);
|
||||
}
|
||||
if (Array.isArray(body["enabledTools"])) {
|
||||
const tools = (body["enabledTools"] as unknown[])
|
||||
.filter((t): t is string => typeof t === "string");
|
||||
setEnabledTools(tools);
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
ok: true,
|
||||
apiKey: getApiKey(),
|
||||
enabledTools: getEnabledTools(),
|
||||
});
|
||||
}
|
||||
|
||||
return Response.json({ error: "Method not allowed" }, { status: 405 });
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`[MUA] WARNUNG: Config-Server konnte nicht gestartet werden (Port ${CONFIG_PORT} belegt?). ` +
|
||||
`Einstellungen über WebGUI sind nicht verfügbar. MCP-Server läuft weiter.`,
|
||||
);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[MUA] ${MUA_SERVER_NAME} v${MUA_VERSION} listening on ${HOST}:${PORT} (MCP) + 127.0.0.1:${CONFIG_PORT} (config)`,
|
||||
`[MUA] ${MUA_SERVER_NAME} v${MUA_VERSION} listening on ${HOST}:${PORT} (MCP)` +
|
||||
(configServer ? ` + 127.0.0.1:${CONFIG_PORT} (config)` : " (config: NICHT VERFÜGBAR)"),
|
||||
);
|
||||
|
||||
// Graceful shutdown
|
||||
|
||||
Reference in New Issue
Block a user