// Load environment variables from .env file first import dotenv from 'dotenv'; dotenv.config(); import express from 'express'; import compression from 'compression'; import { handler } from './dist/server/entry.mjs'; import path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const app = express(); const PORT = process.env.PORT || 3000; // Enable gzip/brotli compression app.use(compression()); // Set minimal secure headers for SSR responses app.use((req, res, next) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin'); res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless'); // Gate SSR CSP to avoid breaking inline scripts unless explicitly enabled if (process.env.ENABLE_SSR_CSP === '1') { res.setHeader( 'Content-Security-Policy', "default-src 'self' https://365devnet.eu https://*.365devnet.eu; " + "script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https://chat.365devnet.eu; " + "style-src 'self' 'unsafe-inline'; " + "img-src 'self' data: https: blob:; " + "font-src 'self' data:; " + "connect-src 'self' https://365devnet.eu https://*.365devnet.eu https://chat.365devnet.eu https://git.365devnet.eu wss://chat.365devnet.eu; " + "frame-src 'self' https://chat.365devnet.eu; " + "frame-ancestors 'none'; " + "base-uri 'self'; " + "form-action 'self'" ); } next(); }); // Serve static assets from the dist/client directory app.use(express.static(path.join(__dirname, 'dist/client'))); // Handle all SSR requests with Astro's handler app.all('*', handler); app.listen(PORT, () => { const isProduction = process.env.NODE_ENV === 'production'; const domain = isProduction ? '365devnet.eu' : `localhost:${PORT}`; const protocol = isProduction ? 'https' : 'http'; console.log(`Server running with compression on ${protocol}://${domain}`); if (!isProduction) { console.log(`Development server accessible at http://localhost:${PORT}`); } });