import express from 'express'; import path from 'node:path'; import helmet from 'helmet'; import cors from 'cors'; import http from 'node:http'; import https from 'node:https'; import { URL } from 'node:url'; import { fileURLToPath } from 'node:url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const PORT = Number(process.env.PORT) || 3000; const HOST = process.env.HOST || '0.0.0.0'; const RUST_ENGINE_BASE = process.env.RUST_ENGINE_BASE || process.env.RUST_ENGINE_URL || 'http://rust-engine:8000'; const STORAGE_DIR = path.resolve(process.env.ASTRA_STORAGE || '/app/storage'); app.set('trust proxy', true); app.use(helmet({ contentSecurityPolicy: false })); app.use(cors()); app.get('/api/healthz', (_req, res) => { res.json({ status: 'ok', upstream: RUST_ENGINE_BASE }); }); // Proxy all /api/* calls (including POST bodies, multipart uploads, etc.) app.use('/api', (req, res) => { const targetUrl = new URL(req.originalUrl, RUST_ENGINE_BASE); const client = targetUrl.protocol === 'https:' ? https : http; const headers = { ...req.headers, host: targetUrl.host }; const proxyReq = client.request( targetUrl, { method: req.method, headers, }, (upstream) => { res.status(upstream.statusCode || 502); for (const [key, value] of Object.entries(upstream.headers)) { if (typeof value !== 'undefined') { res.setHeader(key, value); } } upstream.pipe(res); } ); proxyReq.on('error', (err) => { console.error('API proxy error:', err); if (!res.headersSent) { res.status(502).json({ error: 'proxy_failed' }); } else { res.end(); } }); req.pipe(proxyReq); }); // Serve static frontend const distDir = path.resolve(__dirname, 'dist'); app.use(express.static(distDir)); // Expose imported files for the UI (read-only) app.use('/storage', express.static(STORAGE_DIR)); // SPA fallback (Express 5 requires middleware instead of bare '*') app.use((req, res) => { res.sendFile(path.join(distDir, 'index.html')); }); app.listen(PORT, HOST, () => { console.log(`Web app server listening on http://${HOST}:${PORT}`); console.log(`Proxying to rust engine at ${RUST_ENGINE_BASE}`); });