From 86277e20594d18909c95e8f8c8e21075eb69ab74 Mon Sep 17 00:00:00 2001 From: Gronod Date: Wed, 27 May 2026 23:11:19 +0100 Subject: [PATCH 1/2] fix: serve frontend static files and handle SPA routes (fixes #57) --- server/app.js | 41 ++++++- server/index.js | 289 +----------------------------------------------- 2 files changed, 42 insertions(+), 288 deletions(-) diff --git a/server/app.js b/server/app.js index 22637fc..9490b9f 100644 --- a/server/app.js +++ b/server/app.js @@ -15,6 +15,7 @@ const swaggerUi = require('swagger-ui-express'); const swaggerJsdoc = require('swagger-jsdoc'); const YAML = require('yamljs'); const path = require('path'); +const fs = require('fs'); const { version } = require('../package.json'); const sabnzbdRoutes = require('./routes/sabnzbd'); @@ -132,7 +133,7 @@ function createApp({ skipRateLimits = false } = {}) { * version: * type: string * description: sofarr version - * example: "1.7.25" + * example: "1.7.27" * x-code-samples: * - lang: curl * label: cURL @@ -232,6 +233,44 @@ function createApp({ skipRateLimits = false } = {}) { app.use('/api/status', statusRoutes); app.use('/api/history', historyRoutes); + // --------------------------------------------------------------------------- + // Static files — served before API routes + // index.html is served manually so we can inject the CSP nonce + // --------------------------------------------------------------------------- + const PUBLIC_DIR = path.join(__dirname, '../public'); + const INDEX_HTML = path.join(PUBLIC_DIR, 'index.html'); + + // Serve all static assets (js, css, images, icons) except index.html. + // JS and CSS get no-cache so browsers revalidate on every load (ETag still + // avoids re-downloading unchanged files; only a deploy changes the ETag). + app.use(express.static(PUBLIC_DIR, { + index: false, + setHeaders(res, filePath) { + if (filePath.endsWith('.js') || filePath.endsWith('.css')) { + res.setHeader('Cache-Control', 'no-cache'); + } + } + })); + + // Serve index.html with CSP nonce injected into