Hub: der Dienst laeuft zentral statt auf dem Stream-PC
Zwei Dinge, die Reichweite bringen sollen, hingen bisher daran, dass jemand vor seinem Rechner sitzt: der Discord-Rollen-Knopf und die Go-Live- Ankuendigung. Beide brauchen nur Internet. Der Schnitt verlaeuft entlang einer Frage: braucht die Aufgabe eine Datei oder ein Programm, das nur auf dem Stream-PC existiert? Hub (LXC) Ingest (Abdus PC) --------- ----------------- Chat, Zuschauerzahlen OBS-Wiedergabepuffer Discord: Knopf und Go-Live !clip, Rendern, Untertitel Overlay-Seiten fuer OBS Beide schreiben in ihre eigene Datenbank. Eine gemeinsame waere eine Netzwerkfreigabe fuer SQLite - der zuverlaessigste bekannte Weg zu einer beschaedigten Datei. Das kostet ADR-0005 seine Hauptbegruendung: "bindet nur auf 127.0.0.1" gilt fuer den Hub nicht mehr. An die Stelle treten ein Passwort mit signiertem Sitzungs-Cookie fuer alles, was ein Mensch bedient, und ein zufaelliger Schluessel in der Adresse fuer die Browser-Sources. Der Schluessel ist kein schoenes Verfahren - er steht in jedem OBS-Profil -, aber eine Browser-Source kann kein Formular ausfuellen und keinen Login durchhalten. `publicUrl` haengt der OAuth-Rueckruf daran. Twitch vergleicht die Redirect-URI zeichengenau, und ein fehlender Schraegstrich sieht im Fehlertext aus wie ein falsches Client-Secret. Die Routen der Einrichtungsseite sind aus ingest/server.ts herausgeloest, weil sie jetzt an zwei Servern haengen. Begruendung und Konsequenzen in ADR-0008. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e18336c57f
commit
3b606e36fb
8 files changed
+985
-10
No files matched your search
@@ -59,18 +59,45 @@ async function handle(
|
||||
req: http.IncomingMessage, res: http.ServerResponse, deps: ServerDeps
|
||||
): Promise<void> {
|
||||
const url = new URL(req.url ?? '/', `http://localhost:${deps.port}`);
|
||||
// Auf dem Stream-PC ist die Einrichtung das Einzige, was dieser Server
|
||||
// kann - also faengt die Wurzel dorthin. Im Hub steht auf / die
|
||||
// Overlay-Uebersicht, deshalb liegt die Weiche hier und nicht in
|
||||
// `setupRoutes`.
|
||||
if (url.pathname === '/') {
|
||||
res.writeHead(303, { location: '/setup' });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
if (await setupRoutes(req, res, deps, url)) return;
|
||||
res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
|
||||
res.end('Nicht gefunden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Routen der Einrichtung, ohne 404 am Ende.
|
||||
*
|
||||
* Ausgelagert, weil sie seit dem zentralen Betrieb an zwei Servern haengen:
|
||||
* hier auf dem Stream-PC und im Overlay-Server des Hubs. Der Rueckgabewert
|
||||
* sagt, ob die Anfrage beantwortet wurde - wer sie einbindet, macht sonst
|
||||
* selbst weiter.
|
||||
*/
|
||||
export async function setupRoutes(
|
||||
req: http.IncomingMessage, res: http.ServerResponse, deps: ServerDeps, url: URL
|
||||
): Promise<boolean> {
|
||||
const html = (body: string, code = 200) => {
|
||||
res.writeHead(code, { 'content-type': 'text/html; charset=utf-8',
|
||||
'cache-control': 'no-store', 'referrer-policy': 'no-referrer' });
|
||||
res.end(body);
|
||||
return true;
|
||||
};
|
||||
const back = (kind: 'ok' | 'err', text: string) => {
|
||||
res.writeHead(303, { location: `/setup?${kind}=${encodeURIComponent(text)}` });
|
||||
res.end();
|
||||
return true;
|
||||
};
|
||||
|
||||
// ---- Einrichtungsseite
|
||||
if (url.pathname === '/' || url.pathname === '/setup') {
|
||||
if (url.pathname === '/setup') {
|
||||
const ok = url.searchParams.get('ok');
|
||||
const err = url.searchParams.get('err');
|
||||
return html(setupPage(secretStatus(), {
|
||||
@@ -119,7 +146,7 @@ async function handle(
|
||||
try {
|
||||
res.writeHead(303, { location: authorizeUrl(role, deps.port) });
|
||||
res.end();
|
||||
return;
|
||||
return true;
|
||||
} catch (err) {
|
||||
return back('err', (err as Error).message);
|
||||
}
|
||||
@@ -144,9 +171,8 @@ async function handle(
|
||||
if (url.pathname === '/health') {
|
||||
res.writeHead(200, { 'content-type': 'application/json; charset=utf-8' });
|
||||
res.end(JSON.stringify(deps.health(), null, 2));
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
|
||||
res.end('Nicht gefunden');
|
||||
return false;
|
||||
}
|
||||
Reference in new issue
Block a user