fix: add User-Agent, dual timeout, done-guard, and response logging to _fetchTimeout
- User-Agent header (Spotify may throttle anonymous requests) - req.setTimeout + socket.setTimeout for belt-and-suspenders - done() guard prevents double-resolve/reject - [sp-http] log shows status code of each Spotify response so logs reveal whether the hang is before or after HTTP headers arrive Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
f4766acc74
commit
d2cb1bed68
1 file changed
+16
-7
@@ -72,28 +72,37 @@ function parseSpotifyUrl(url) {
|
|||||||
function _fetchTimeout(url, opts = {}, ms = 10000) {
|
function _fetchTimeout(url, opts = {}, ms = 10000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const u = new URL(url);
|
const u = new URL(url);
|
||||||
|
const label = u.hostname + u.pathname.slice(0, 40);
|
||||||
|
const done = (fn) => { if (!done.called) { done.called = true; fn(); } };
|
||||||
const req = https.request({
|
const req = https.request({
|
||||||
hostname: u.hostname, port: 443,
|
hostname: u.hostname, port: 443,
|
||||||
path: u.pathname + u.search,
|
path: u.pathname + u.search,
|
||||||
method: opts.method || 'GET',
|
method: opts.method || 'GET',
|
||||||
headers: opts.headers || {},
|
headers: {
|
||||||
|
'User-Agent': 'NovaSonic/1.0',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
...opts.headers,
|
||||||
|
},
|
||||||
}, res => {
|
}, res => {
|
||||||
|
console.log(`[sp-http] ${res.statusCode} ${label}`);
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
res.on('data', c => chunks.push(c));
|
res.on('data', c => chunks.push(c));
|
||||||
res.on('end', () => {
|
res.on('end', () => {
|
||||||
const body = Buffer.concat(chunks).toString();
|
const body = Buffer.concat(chunks).toString('utf8');
|
||||||
resolve({
|
done(() => resolve({
|
||||||
ok: res.statusCode >= 200 && res.statusCode < 300,
|
ok: res.statusCode >= 200 && res.statusCode < 300,
|
||||||
status: res.statusCode,
|
status: res.statusCode,
|
||||||
headers: { get: h => res.headers[h.toLowerCase()] ?? null },
|
headers: { get: h => res.headers[h.toLowerCase()] ?? null },
|
||||||
json: () => { try { return Promise.resolve(JSON.parse(body)); } catch(e) { return Promise.reject(e); } },
|
json: () => { try { return Promise.resolve(JSON.parse(body)); } catch(e) { return Promise.reject(e); } },
|
||||||
text: () => Promise.resolve(body),
|
text: () => Promise.resolve(body),
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
res.on('error', reject);
|
res.on('error', e => done(() => reject(e)));
|
||||||
});
|
});
|
||||||
req.on('socket', s => s.setTimeout(ms, () => req.destroy(new Error(`Spotify nicht erreichbar (Timeout ${ms}ms) — api.spotify.com blockiert?`))));
|
// Two-layer timeout: req-level (fires after ms of total inactivity) + socket-level
|
||||||
req.on('error', reject);
|
req.setTimeout(ms, () => req.destroy(new Error(`Spotify timeout ${ms}ms: ${label}`)));
|
||||||
|
req.on('socket', s => s.setTimeout(ms, () => req.destroy(new Error(`Spotify socket timeout ${ms}ms: ${label}`))));
|
||||||
|
req.on('error', e => done(() => reject(e)));
|
||||||
if (opts.body) req.write(opts.body);
|
if (opts.body) req.write(opts.body);
|
||||||
req.end();
|
req.end();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user