nakama/backend/server.js

103 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const dotenv = require('dotenv');
const path = require('path');
const http = require('http');
const { generalLimiter } = require('./middleware/rateLimiter');
const { initRedis } = require('./utils/redis');
const { initWebSocket } = require('./websocket');
const config = require('./config');
dotenv.config();
const app = express();
const server = http.createServer(app);
// CORS настройки
const corsOptions = {
origin: config.corsOrigin === '*' ? '*' : config.corsOrigin.split(','),
credentials: true,
optionsSuccessStatus: 200
};
// Middleware
app.use(cors(corsOptions));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/uploads', express.static(path.join(__dirname, config.uploadsDir)));
// Доверять proxy для правильного IP (для rate limiting за nginx/cloudflare)
if (config.isProduction()) {
app.set('trust proxy', 1);
}
// Rate limiting
app.use('/api', generalLimiter);
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'ok',
environment: config.nodeEnv,
timestamp: new Date().toISOString()
});
});
// MongoDB подключение
mongoose.connect(config.mongoUri, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log(`✅ MongoDB подключена: ${config.mongoUri.replace(/\/\/.*@/, '//***@')}`);
// Инициализировать Redis (опционально)
if (config.redisUrl) {
initRedis().catch(err => console.log('⚠️ Redis недоступен, работаем без кэша'));
} else {
console.log(' Redis не настроен, кэширование отключено');
}
})
.catch(err => console.error('❌ Ошибка MongoDB:', err));
// Routes
app.use('/api/auth', require('./routes/auth'));
app.use('/api/posts', require('./routes/posts'));
app.use('/api/users', require('./routes/users'));
app.use('/api/notifications', require('./routes/notifications'));
app.use('/api/search', require('./routes/search'));
app.use('/api/search/posts', require('./routes/postSearch'));
app.use('/api/moderation', require('./routes/moderation'));
app.use('/api/statistics', require('./routes/statistics'));
// Базовый роут
app.get('/', (req, res) => {
res.json({ message: 'NakamaSpace API работает' });
});
// Инициализировать WebSocket
initWebSocket(server);
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('SIGTERM получен, закрываем сервер...');
server.close(() => {
console.log('Сервер закрыт');
mongoose.connection.close(false, () => {
console.log('MongoDB соединение закрыто');
process.exit(0);
});
});
});
server.listen(config.port, '0.0.0.0', () => {
console.log(`🚀 Сервер запущен`);
console.log(` Порт: ${config.port}`);
console.log(` Окружение: ${config.nodeEnv}`);
console.log(` API: http://0.0.0.0:${config.port}/api`);
if (config.isDevelopment()) {
console.log(` Frontend: ${config.frontendUrl}`);
}
});