From b8d50d56b7336e7e2670c0383a826d58ec1cd663 Mon Sep 17 00:00:00 2001 From: Heidi Date: Mon, 22 Jun 2026 20:01:36 +0100 Subject: [PATCH] ai generated solutions to our ai generated problems --- server.cjs | 70 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/server.cjs b/server.cjs index 3bd79e6..586825c 100644 --- a/server.cjs +++ b/server.cjs @@ -158,7 +158,7 @@ const CSP_DIRECTIVES = [ "style-src-elem 'self'", "style-src-attr 'unsafe-inline'", "img-src 'self' data: blob: https://*.basemaps.cartocdn.com https://basemaps.cartocdn.com", - "media-src https://*.dzcdn.net https://*.deezer.com", + "media-src 'self' https://*.dzcdn.net https://*.deezer.com", "font-src 'self' data:", "connect-src 'self' https://challenges.cloudflare.com", "frame-src https://challenges.cloudflare.com", @@ -190,6 +190,11 @@ const mimeTypes = { '.png': 'image/png', '.svg': 'image/svg+xml', '.webp': 'image/webp', + '.mp4': 'video/mp4', + '.webm': 'video/webm', + '.ogg': 'video/ogg', + '.mp3': 'audio/mpeg', + '.wav': 'audio/wav', } function send(res, status, body, headers = {}) { @@ -2429,8 +2434,8 @@ function serveStatic(req, res) { return send(res, 403, 'Forbidden', { 'content-type': 'text/plain; charset=utf-8' }) } - fs.readFile(filePath, (error, data) => { - if (error) { + fs.stat(filePath, (error, stat) => { + if (error || !stat.isFile()) { fs.readFile(path.join(DIST_DIR, 'index.html'), (indexError, indexData) => { if (indexError) { return send(res, 404, 'Build not found. Run npm run build first.', { @@ -2445,14 +2450,63 @@ function serveStatic(req, res) { const ext = path.extname(filePath) if (ext === '.html') { - sendHtml(req, res, data) + fs.readFile(filePath, (htmlError, htmlData) => { + if (htmlError) { + return send(res, 500, 'Error reading file', { 'content-type': 'text/plain; charset=utf-8' }) + } + sendHtml(req, res, htmlData) + }) return } - send(res, 200, data, { - 'content-type': mimeTypes[ext] || 'application/octet-stream', - 'cache-control': 'public, max-age=31536000, immutable', - }) + const contentType = mimeTypes[ext] || 'application/octet-stream' + const range = req.headers.range + + if (range) { + const parts = range.replace(/bytes=/, '').split('-') + const start = parseInt(parts[0], 10) + const end = parts[1] ? parseInt(parts[1], 10) : stat.size - 1 + + if (isNaN(start) || start < 0 || start >= stat.size || end >= stat.size || start > end) { + res.writeHead(416, { + ...securityHeaders(req), + 'Content-Range': `bytes */${stat.size}`, + 'Accept-Ranges': 'bytes', + 'content-type': 'text/plain', + }) + return res.end('Requested Range Not Satisfiable') + } + + const chunksize = end - start + 1 + const fileStream = fs.createReadStream(filePath, { start, end }) + const headers = { + ...securityHeaders(req), + 'Content-Range': `bytes ${start}-${end}/${stat.size}`, + 'Accept-Ranges': 'bytes', + 'Content-Length': String(chunksize), + 'content-type': contentType, + 'cache-control': 'public, max-age=31536000, immutable', + } + res.writeHead(206, headers) + fileStream.pipe(res) + fileStream.on('error', (err) => { + console.error(`Stream error serving ${filePath}:`, err) + }) + } else { + const fileStream = fs.createReadStream(filePath) + const headers = { + ...securityHeaders(req), + 'Accept-Ranges': 'bytes', + 'Content-Length': String(stat.size), + 'content-type': contentType, + 'cache-control': 'public, max-age=31536000, immutable', + } + res.writeHead(200, headers) + fileStream.pipe(res) + fileStream.on('error', (err) => { + console.error(`Stream error serving ${filePath}:`, err) + }) + } }) }