From b097d7b03352bcbddea53571ac65c048e4c16d45 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 11 Jun 2026 18:41:16 -0500 Subject: [PATCH] refactor(desktop): use native fetch in dashboard-token Node >=18 / Electron 40 ship fetch; the hand-rolled http/https.request plumbing buys nothing. AbortSignal.timeout replaces the socket timeout, protocol guard and >=400 rejection semantics preserved. 13/13 unit tests and the live web_server.py repro both green over the new transport. --- apps/desktop/electron/dashboard-token.cjs | 53 +++++++---------------- 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/apps/desktop/electron/dashboard-token.cjs b/apps/desktop/electron/dashboard-token.cjs index 639091a1f79..1a9ca50ad9c 100644 --- a/apps/desktop/electron/dashboard-token.cjs +++ b/apps/desktop/electron/dashboard-token.cjs @@ -7,47 +7,26 @@ * probes still pass while /api/ws rejects the renderer's token. */ -const http = require('node:http') -const https = require('node:https') - const DEFAULT_TOKEN_FETCH_TIMEOUT_MS = 3_000 -function fetchPublicText(url, options = {}) { - return new Promise((resolve, reject) => { - let parsed - try { - parsed = new URL(url) - } catch (error) { - reject(new Error(`Invalid URL: ${error.message}`)) - return +async function fetchPublicText(url, options = {}) { + const { protocol } = new URL(url) + if (protocol !== 'http:' && protocol !== 'https:') { + throw new Error(`Unsupported Hermes backend URL protocol: ${protocol}`) + } + + const timeoutMs = options.timeoutMs ?? DEFAULT_TOKEN_FETCH_TIMEOUT_MS + const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) }).catch(error => { + if (error.name === 'TimeoutError') { + throw new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`) } - - if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') { - reject(new Error(`Unsupported Hermes backend URL protocol: ${parsed.protocol}`)) - return - } - - const client = parsed.protocol === 'https:' ? https : http - const timeoutMs = options.timeoutMs ?? DEFAULT_TOKEN_FETCH_TIMEOUT_MS - const req = client.request(parsed, { method: options.method || 'GET' }, res => { - const chunks = [] - res.on('data', chunk => chunks.push(chunk)) - res.on('end', () => { - const text = Buffer.concat(chunks).toString('utf8') - if ((res.statusCode || 500) >= 400) { - reject(new Error(`${res.statusCode}: ${text || res.statusMessage}`)) - return - } - resolve(text) - }) - }) - - req.on('error', reject) - req.setTimeout(timeoutMs, () => { - req.destroy(new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`)) - }) - req.end() + throw error }) + const text = await res.text() + + if (!res.ok) throw new Error(`${res.status}: ${text || res.statusText}`) + + return text } function extractInjectedDashboardToken(html) {