diff --git a/server/index.mjs b/server/index.mjs index 9d1804b..ae3c15b 100644 --- a/server/index.mjs +++ b/server/index.mjs @@ -85,30 +85,37 @@ function sendFile(res, filePath, status = 200) { createReadStream(filePath).pipe(res) } -function serveStatic(req, res) { - // Strip query, prevent path traversal, default to index.html (SPA fallback). - const urlPath = decodeURIComponent((req.url || '/').split('?')[0]) +// Resolve a request path to an existing static file inside dist/, or null. +function resolveStaticFile(url) { + const urlPath = decodeURIComponent((url || '/').split('?')[0]) const safe = normalize(urlPath).replace(/^(\.\.[/\\])+/, '') - let filePath = join(DIST, safe) - - if (!filePath.startsWith(DIST)) { - res.statusCode = 403 - return res.end('Forbidden') - } - if (existsSync(filePath) && statSync(filePath).isFile()) { - return sendFile(res, filePath) - } - // SPA fallback - const indexFile = join(DIST, 'index.html') - if (existsSync(indexFile)) return sendFile(res, indexFile) - res.statusCode = 404 - res.end('Not found') + const filePath = join(DIST, safe) + if (!filePath.startsWith(DIST)) return null + if (existsSync(filePath) && statSync(filePath).isFile()) return filePath + return null } +const INDEX_HTML = join(DIST, 'index.html') + const server = http.createServer((req, res) => { const url = req.url || '/' + + // 1) Known ABS paths → forward upstream. if (isProxied(url)) return proxy(req, res) - return serveStatic(req, res) + + // 2) An existing static asset of the SPA → serve it. + const file = resolveStaticFile(url) + if (file) return sendFile(res, file) + + // 3) A browser navigating to a client-side route → serve the SPA shell. + const accept = String(req.headers.accept || '') + if (req.method === 'GET' && accept.includes('text/html') && existsSync(INDEX_HTML)) { + return sendFile(res, INDEX_HTML) + } + + // 4) Anything else (any other API/data request) → forward to ABS, so the real + // server never needs to be exposed on its own domain. + return proxy(req, res) }) server.listen(PORT, HOST, () => { diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 8696930..ed8ce71 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -76,10 +76,21 @@ export function Sidebar() { collapsed ? 'w-[68px]' : 'w-60', )} > -