fix: switch Spotify HTTP to https module with socket.setTimeout for OS-level timeout
undici cannot abort a TCP connect in progress even with AbortController. Node's https.request + socket.setTimeout fires at the OS socket level and aborts within ms even when the TCP SYN is silently dropped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
d2620519aa
commit
f4766acc74
1 file changed
+30
-6
@@ -67,12 +67,36 @@ function parseSpotifyUrl(url) {
|
||||
return { type: m[1], id: m[2] };
|
||||
}
|
||||
|
||||
// AbortSignal.timeout() is unreliable in Node/undici when TCP connect is blocked.
|
||||
// Use AbortController + setTimeout instead — always fires from Node's event loop.
|
||||
function _fetchTimeout(url, opts, ms = 10000) {
|
||||
const ctrl = new AbortController();
|
||||
const timer = setTimeout(() => ctrl.abort(), ms);
|
||||
return fetch(url, { ...opts, signal: ctrl.signal }).finally(() => clearTimeout(timer));
|
||||
// undici (native fetch) cannot abort a pending TCP connect even with AbortController.
|
||||
// Use Node's https module with socket.setTimeout() — fires at OS level during connect.
|
||||
function _fetchTimeout(url, opts = {}, ms = 10000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const u = new URL(url);
|
||||
const req = https.request({
|
||||
hostname: u.hostname, port: 443,
|
||||
path: u.pathname + u.search,
|
||||
method: opts.method || 'GET',
|
||||
headers: opts.headers || {},
|
||||
}, res => {
|
||||
const chunks = [];
|
||||
res.on('data', c => chunks.push(c));
|
||||
res.on('end', () => {
|
||||
const body = Buffer.concat(chunks).toString();
|
||||
resolve({
|
||||
ok: res.statusCode >= 200 && res.statusCode < 300,
|
||||
status: res.statusCode,
|
||||
headers: { get: h => res.headers[h.toLowerCase()] ?? null },
|
||||
json: () => { try { return Promise.resolve(JSON.parse(body)); } catch(e) { return Promise.reject(e); } },
|
||||
text: () => Promise.resolve(body),
|
||||
});
|
||||
});
|
||||
res.on('error', reject);
|
||||
});
|
||||
req.on('socket', s => s.setTimeout(ms, () => req.destroy(new Error(`Spotify nicht erreichbar (Timeout ${ms}ms) — api.spotify.com blockiert?`))));
|
||||
req.on('error', reject);
|
||||
if (opts.body) req.write(opts.body);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
let _spTokenCache = null;
|
||||
|
||||
Reference in new issue
Block a user