Fix screenshot fallback query and API 404 hang

Two pre-existing bugs surfaced during deploy:

- /api/devices/:id/screenshot fell back to a query referencing
  screenshots.created_at, but the schema column is captured_at. Threw
  SqliteError 500 whenever the in-memory cache was cold (e.g. just
  after a server restart).

- The SPA catch-all at /* served index.html for non-/api paths but did
  nothing for unmatched /api/ paths — the response hung until the
  upstream timeout (524 from Cloudflare at 15s). Now returns 404 JSON.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ScreenTinker 2026-04-28 14:49:10 -05:00
parent 8ec33721f7
commit f8cc62308f

View file

@ -236,7 +236,7 @@ app.get('/api/devices/:id/screenshot', (req, res) => {
res.set('Cache-Control', 'no-cache');
return res.send(buffer);
}
const screenshot = sdb.prepare('SELECT * FROM screenshots WHERE device_id = ? ORDER BY created_at DESC LIMIT 1').get(req.params.id);
const screenshot = sdb.prepare('SELECT * FROM screenshots WHERE device_id = ? ORDER BY captured_at DESC LIMIT 1').get(req.params.id);
if (!screenshot) return res.status(404).json({ error: 'No screenshot available' });
const safePath = path.resolve(config.screenshotsDir, path.basename(screenshot.filepath));
if (!safePath.startsWith(path.resolve(config.screenshotsDir))) return res.status(403).json({ error: 'Invalid path' });
@ -438,11 +438,13 @@ app.get('/download/apk', (req, res) => {
}
});
// SPA fallback for app routes
// SPA fallback for app routes. Unmatched /api/ paths return 404 so misrouted
// clients fail fast instead of hanging until Cloudflare's 15s upstream timeout.
app.get('*', (req, res) => {
if (!req.path.startsWith('/api/')) {
res.sendFile(path.join(config.frontendDir, 'index.html'));
if (req.path.startsWith('/api/')) {
return res.status(404).json({ error: 'Not found' });
}
res.sendFile(path.join(config.frontendDir, 'index.html'));
});
const listenPort = hasSsl ? config.httpsPort : config.port;