require('dotenv').config({ path: require('path').join(__dirname, '../.env') }); const express = require('express'); const session = require('express-session'); // const helmet = require('helmet'); // Geçici olarak devre dışı const cors = require('cors'); const logger = require('./config/logger'); const sessionConfig = require('./config/session'); const { testConnection } = require('./config/database'); const errorHandler = require('./middlewares/errorHandler'); const { apiLimiter } = require('./middlewares/rateLimiter'); const app = express(); const PORT = process.env.PORT || 3000; // Security middleware - Helmet'i tamamen kaldır (CORS ve mixed content sorunları için) // app.use(helmet()); // Geçici olarak devre dışı // CORS - Her yerden erişime izin ver (tüm route'larda) app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization'); res.header('Access-Control-Allow-Credentials', 'true'); // OPTIONS request'i için hemen cevap ver if (req.method === 'OPTIONS') { return res.sendStatus(200); } next(); }); // CORS middleware'i de ekle (çift güvence) app.use(cors({ origin: '*', // Tüm origin'lere izin ver credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Origin', 'Accept'], })); // Body parsing middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Serve static files (landing page and frontend build) const path = require('path'); app.use(express.static(path.join(__dirname, 'public'), { setHeaders: (res, filePath) => { // CORS headers for ALL static files (CSS, JS, images, etc.) res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Methods', 'GET, OPTIONS'); res.set('Access-Control-Allow-Headers', 'Content-Type, Accept, Origin'); res.set('Access-Control-Allow-Credentials', 'true'); // Content-Type header'larını doğru ayarla if (filePath.endsWith('.js')) { res.set('Content-Type', 'application/javascript; charset=utf-8'); } else if (filePath.endsWith('.css')) { res.set('Content-Type', 'text/css; charset=utf-8'); } } })); // Serve landing page at /landing route app.get('/landing', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'landing.html')); }); // Session middleware app.use(session(sessionConfig)); // Rate limiting app.use('/api', apiLimiter); // Request logging app.use((req, res, next) => { logger.info(`${req.method} ${req.path}`, { ip: req.ip, userAgent: req.get('user-agent'), }); next(); }); // Health check app.get('/health', (req, res) => { res.json({ success: true, message: 'Server is running', timestamp: new Date().toISOString(), }); }); // API Routes app.use('/api/auth', require('./routes/auth.routes')); app.use('/api/companies', require('./routes/company.routes')); app.use('/api/tokens', require('./routes/token.routes')); app.use('/api/templates', require('./routes/template.routes')); app.use('/api/settings', require('./routes/settings.routes')); app.use('/api/ollama', require('./routes/ollama.routes')); app.use('/api/stats', require('./routes/stats.routes')); // Public tracking route (no rate limit on this specific route) app.use('/t', require('./routes/tracking.routes')); // Serve frontend SPA (must be after API routes) app.get('*', (req, res, next) => { // Skip if it's an API route, tracking route, or landing page if (req.path.startsWith('/api') || req.path.startsWith('/t') || req.path.startsWith('/landing') || req.path.startsWith('/health')) { return next(); } // CORS headers for HTML res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type'); // Serve frontend index.html for all other routes const frontendPath = path.join(__dirname, 'public', 'dist', 'index.html'); res.sendFile(frontendPath, (err) => { if (err) { // If frontend build doesn't exist, return 404 next(); } }); }); // 404 handler app.use((req, res) => { res.status(404).json({ success: false, error: 'Endpoint not found', }); }); // Error handler (must be last) app.use(errorHandler); // Start server const startServer = async () => { try { // Test database connection await testConnection(); // Start listening on all interfaces (0.0.0.0) to allow remote access app.listen(PORT, '0.0.0.0', () => { logger.info(`🚀 Server is running on port ${PORT}`); logger.info(`📊 Environment: ${process.env.NODE_ENV || 'development'}`); logger.info(`🔗 Health check: http://0.0.0.0:${PORT}/health`); console.log(`\n✨ Oltalama Backend Server Started!`); console.log(`🌐 API: http://0.0.0.0:${PORT}/api`); console.log(`🎯 Tracking: http://0.0.0.0:${PORT}/t/:token`); console.log(`🌍 Server listening on all interfaces (0.0.0.0:${PORT})\n`); }); } catch (error) { logger.error('Failed to start server:', error); process.exit(1); } }; startServer(); module.exports = app;