This repository has been archived on 2026-05-04. You can view files and clone it, but cannot push or open issues or pull requests.
Galaxy-Strike-Online/API/server.js
2026-01-24 16:47:19 -04:00

155 lines
4.3 KiB
JavaScript

const express = require('express');
const http = require('http');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const rateLimit = require('rate-limiter-flexible');
require('dotenv').config();
const logger = require('./utils/logger');
const connectDB = require('./config/database');
const authRoutes = require('./routes/auth');
const serverRoutes = require('./routes/servers');
const modsRoutes = require('./routes/mods');
const { errorHandler, notFound } = require('./middleware/errorHandler');
// Override console.error to properly log error objects
const originalConsoleError = console.error;
console.error = (...args) => {
args.forEach(arg => {
if (arg instanceof Error) {
logger.error('Console Error:', {
message: arg.message,
stack: arg.stack,
name: arg.name
});
} else if (typeof arg === 'object' && arg !== null) {
logger.error('Console Error Object:', arg);
} else {
logger.error('Console Error:', arg);
}
});
};
const app = express();
const server = http.createServer(app);
// Middleware
app.use(helmet());
app.use(compression());
app.use(cors({
origin: ["https://galaxystrike.online", "https://api.korvarix.com", "http://api.korvarix.com:3001"],
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Static file serving
app.use(express.static('../Website/dist'));
// Rate limiting
const { RateLimiterMemory } = require('rate-limiter-flexible');
const limiter = new RateLimiterMemory({
keyGenerator: (req) => req.ip,
points: 100, // limit each IP to 100 requests per windowMs
duration: 900, // 15 minutes
blockDuration: 900, // Block for 15 minutes
});
app.use('/api/', async (req, res, next) => {
try {
const resLimiter = await limiter.consume(req.ip);
if (!resLimiter.remainingPoints) {
return res.status(429).json({ error: 'Too many requests, please try again later.' });
}
next();
} catch (error) {
next();
}
});
// Routes - API Server Only (Auth + Server Browser + Mods)
app.use('/api/auth', authRoutes);
app.use('/api/servers', serverRoutes);
app.use('/api/mods', modsRoutes);
// Health check
app.get('/health', (req, res) => {
res.status(200).json({
status: 'API Server OK',
service: 'galaxystrikeonline-api',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
});
// API version endpoint
app.get('/api/ssc/version', (req, res) => {
res.status(200).json({
version: '1.0.0',
service: 'galaxystrikeonline-api',
timestamp: new Date().toISOString()
});
});
// Fallback route for SPA - only serve index.html for non-API routes
app.get('*', (req, res) => {
// Don't try to serve index.html for API routes
if (req.path.startsWith('/api/')) {
return res.status(404).json({ error: 'API endpoint not found' });
}
// Try dist first (for built files), fallback to public (for development)
const distPath = require('path').resolve(__dirname, '../dist/index.html');
const publicPath = require('path').resolve(__dirname, '../public/index.html');
const fs = require('fs');
if (fs.existsSync(distPath)) {
res.sendFile(distPath);
} else if (fs.existsSync(publicPath)) {
res.sendFile(publicPath);
} else {
res.status(404).json({ error: 'Frontend not found' });
}
});
// Error handling
app.use(notFound);
app.use(errorHandler);
// Initialize database only (no game systems for API server)
async function startServer() {
try {
// Connect to database
await connectDB();
logger.info('Database connected successfully');
// Start API server
const PORT = process.env.PORT || 3001;
server.listen(PORT, () => {
logger.info(`API Server running on port ${PORT}`);
logger.info('API Server handles: Authentication, Server Browser, User Data');
});
} catch (error) {
logger.error('Failed to start API server:', error);
process.exit(1);
}
}
// Handle uncaught errors
process.on('uncaughtException', (error) => {
logger.error('Uncaught Exception:', error);
});
process.on('unhandledRejection', (reason, promise) => {
logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
});
// Handle HTTP server errors
server.on('error', (error) => {
logger.error('HTTP Server error:', error);
});
startServer();
module.exports = { app, server };