From 12a379b51db04308d63288173398d4d0e655ae75 Mon Sep 17 00:00:00 2001 From: jenz Date: Fri, 23 Oct 2026 12:47:53 +0100 Subject: [PATCH] well for some reason is the external fetch library failing now, so replaced with whatever fetch node itself has, also changed shell script for starting signaling server to clean it up previous session and finally bothered moving tokens over to .env file --- .gitignore | 1 + start-signaling.sh | 37 +++++++++++++++++++--- streaming-agent/package.json | 4 ++- streaming-agent/signaling-server.js | 48 +++++++++++++++++------------ 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index c9fc5d0..25d69a4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ signaling.log streaming-agent/node_modules/ dxvk-cache mesa-shader-cache +.env diff --git a/start-signaling.sh b/start-signaling.sh index 058a38f..86d954a 100755 --- a/start-signaling.sh +++ b/start-signaling.sh @@ -1,7 +1,34 @@ #!/bin/bash -cd ~/webclient_css_ze/streaming-agent -CF_APP_ID= CF_APP_TOKEN= NAME_SALT= CONTAINER_NAME=css-test node signaling-server.js &> ../signaling.log & -echo "Signaling server started (PID $!), logs at webclient_css_ze/signaling.log" +# Starts the signaling server. Secrets come from .env next to this script +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="$SCRIPT_DIR/.env" -#pkill -f signaling-server.js -#pgrep -f signaling-server.js +if [ ! -f "$ENV_FILE" ]; then + echo "Missing $ENV_FILE — copy .env.example to .env and fill in the values." >&2 + exit 1 +fi + +# Export every variable defined in .env +set -a +source "$ENV_FILE" +set +a + +for var in CF_APP_ID CF_APP_TOKEN NAME_SALT; do + if [ -z "${!var}" ]; then + echo "$var is not set in $ENV_FILE" >&2 + exit 1 + fi +done +export CONTAINER_NAME="${CONTAINER_NAME:-css-test}" + +# Stop any old instance and wait until it is gone (frees port 3000) +pkill -f signaling-server.js || true +for i in $(seq 1 10); do + pgrep -f signaling-server.js > /dev/null || break + sleep 0.5 +done + +cd "$SCRIPT_DIR/streaming-agent" +node signaling-server.js &> "$SCRIPT_DIR/signaling.log" & +echo "Signaling server started (PID $!), logs at $SCRIPT_DIR/signaling.log" diff --git a/streaming-agent/package.json b/streaming-agent/package.json index 074a580..6238ddb 100644 --- a/streaming-agent/package.json +++ b/streaming-agent/package.json @@ -8,8 +8,10 @@ "signaling": "node signaling-server.js" }, "dependencies": { - "node-fetch": "^2.7.0", "ws": "^8.18.0", "express": "^4.21.0" + }, + "engines": { + "node": ">=18" } } diff --git a/streaming-agent/signaling-server.js b/streaming-agent/signaling-server.js index 6cdc570..2860180 100644 --- a/streaming-agent/signaling-server.js +++ b/streaming-agent/signaling-server.js @@ -21,7 +21,7 @@ console.error = (...args) => _origError(`[${new Date().toISOString()}]`, ...args const express = require('express'); const http = require('http'); const WebSocket = require('ws'); -const fetch = require('node-fetch'); +// fetch is built into Node 18+ (node-fetch 2.x threw 'Premature close' on CF responses) const path = require('path'); const { spawn, execSync } = require('child_process'); const dns = require('dns').promises; @@ -40,27 +40,37 @@ if (!CF_APP_ID || !CF_APP_TOKEN) { } // ── Cloudflare API helpers ──────────────────────────────────────────────────── -async function cfPost(path, body) { - const res = await fetch(`${CF_BASE}${path}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${CF_APP_TOKEN}` }, - body: JSON.stringify(body), - }); - const json = await res.json(); - if (json.errorCode) throw new Error(`CF API error: ${json.errorDescription}`); +async function cfRequest(method, path, body) { + const started = Date.now(); + let res, text; + try { + res = await fetch(`${CF_BASE}${path}`, { + method, + headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${CF_APP_TOKEN}` }, + body: JSON.stringify(body), + signal: AbortSignal.timeout(15000), + }); + text = await res.text(); + } catch (e) { + console.error(`[sig] CF ${method} ${path} failed after ${Date.now() - started}ms: ${e.name}: ${e.message}`); + throw new Error('Stream service unreachable, please try again'); + } + let json; + try { + json = JSON.parse(text); + } catch { + console.error(`[sig] CF ${method} ${path} returned non-JSON (HTTP ${res.status}): ${text.slice(0, 300)}`); + throw new Error('Stream service returned an invalid response'); + } + if (json.errorCode) { + console.error(`[sig] CF ${method} ${path} error (HTTP ${res.status}): ${json.errorCode} ${json.errorDescription}`); + throw new Error('Stream setup failed, please try again'); + } return json; } -async function cfPut(path, body) { - const res = await fetch(`${CF_BASE}${path}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${CF_APP_TOKEN}` }, - body: JSON.stringify(body), - }); - const json = await res.json(); - if (json.errorCode) throw new Error(`CF API error: ${json.errorDescription}`); - return json; -} +const cfPost = (path, body) => cfRequest('POST', path, body); +const cfPut = (path, body) => cfRequest('PUT', path, body); // ── Express + WebSocket ─────────────────────────────────────────────────────── const app = express();