103 lines
3.2 KiB
JavaScript
103 lines
3.2 KiB
JavaScript
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}`);
|
||
}
|
||
});
|
||
|