NextNodeTemplate/backend/server.js
DosAi ea61c5f493
Some checks failed
CI/CD / lint-and-build (push) Has been cancelled
feat: Add automatic free port finder for frontend and backend
2025-11-02 17:39:38 +03:00

90 lines
2.9 KiB
JavaScript
Raw Permalink 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.

// Загрузка переменных окружения
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const winstonLogger = require('./config/logger');
const simpleLogger = require('./middleware/logger'); // Простое логирование для разработки
const errorHandler = require('./middleware/errorHandler');
const { generalLimiter } = require('./middleware/rateLimiter');
const app = express();
const { getServerPort } = require('./lib/portFinder');
// Получаем порт (с автоматическим поиском свободного если нужно)
const DEFAULT_PORT = process.env.PORT || 3001;
let PORT = DEFAULT_PORT;
// Middleware
app.use(simpleLogger); // Простое логирование запросов
app.use(generalLimiter); // Rate limiting
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// CORS (настройте под свои нужды)
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
// Health check endpoint
app.get('/api/health', (req, res) => {
res.json({
status: 'ok',
message: 'Server is running',
timestamp: new Date().toISOString(),
});
});
// Пример API endpoint
app.post('/api/example', (req, res) => {
try {
const { data } = req.body;
res.json({ success: true, received: data });
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
// Подключение роутов
const exampleRoutes = require('./routes/example');
app.use('/api/example', exampleRoutes);
// Обработка 404
app.use((req, res) => {
res.status(404).json({
success: false,
error: 'Route not found',
});
});
// Обработка ошибок (должен быть последним middleware)
app.use(errorHandler);
// Запуск сервера с автоматическим поиском свободного порта
(async () => {
try {
PORT = await getServerPort(DEFAULT_PORT, true);
app.listen(PORT, () => {
winstonLogger.info(`🚀 Server is running on http://localhost:${PORT}`);
winstonLogger.info(`📡 Health check: http://localhost:${PORT}/api/health`);
winstonLogger.info(`📝 Environment: ${process.env.NODE_ENV || 'development'}`);
if (PORT !== DEFAULT_PORT) {
winstonLogger.info(
` Используется порт ${PORT} вместо ${DEFAULT_PORT} (занят)`
);
}
});
} catch (error) {
winstonLogger.error(`❌ Ошибка запуска сервера: ${error.message}`);
process.exit(1);
}
})();