/
RomanG9
/
web-nodejs-labs
Обзор
Документация
Войти
/
RomanG9
/
web-nodejs-labs
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
backend/server.js
236 строк
8 KB
unknown
лаба11..234.
19 дек 2025, 02:26
19 дек 2025, 02:26
a2e0064
Код
Авторство
О чём код?
import Fastify from 'fastify'; import FastifyStatic from '@fastify/static'; import fastifyPostgres from '@fastify/postgres'; import fastifyJwt from '@fastify/jwt'; import dotenv from 'dotenv'; import path from 'path'; import { fileURLToPath } from 'url'; // Определяем текущие пути const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Создаём экземпляр Fastify с включённым логированием const fastify = Fastify({ logger: { level: 'info' // Упрощенное логирование без pino-pretty для совместимости } }); // 1. Загрузка конфигурации из .env.local const envPath = path.join(__dirname, '.env.local'); const envResult = dotenv.config({ path: envPath }); if (envResult.error) { console.warn('Файл .env.local не найден, используем значения по умолчанию'); } if (!process.env.DATABASE_URL) { console.warn('DATABASE_URL не найден, используем значение по умолчанию'); process.env.DATABASE_URL = 'postgresql://postgres:postgres@localhost:5432/postgres'; } if (!process.env.PORT) { process.env.PORT = '3000'; } if (!process.env.SECRET_KEY) { console.warn('SECRET_KEY не найден, используем значение по умолчанию'); process.env.SECRET_KEY = 'mysecretkey'; } // 2. Подключение к базе данных и JWT const setupPlugins = async () => { try { await fastify.register(fastifyPostgres, { connectionString: process.env.DATABASE_URL, max: 20, idleTimeoutMillis: 30000 }); await fastify.register(fastifyJwt, { secret: process.env.SECRET_KEY }); } catch (err) { fastify.log.error('Ошибка регистрации плагинов:', err); throw err; } }; // 3. Регистрация маршрутов лабораторных работ (ПЕРЕД статическими файлами) const registerLabRoutes = async (labNumber) => { try { const routePath = path.join(__dirname, 'src', 'routes', `lab${labNumber}`, 'index.js'); console.log('Проверяем путь к маршруту:', routePath); const routes = await import(routePath); fastify.register(routes.default, { prefix: `/api/lab${labNumber}` }); fastify.log.info(`Маршруты lab${labNumber} успешно зарегистрированы`); } catch (err) { if (err.code === 'ERR_MODULE_NOT_FOUND') { fastify.log.warn(`Маршруты lab${labNumber} не найдены (файл отсутствует)`); } else { fastify.log.error(`Ошибка при регистрации lab${labNumber}:`, err); process.exit(1); } } }; // Регистрируем маршруты для lab7, lab8, lab9, lab10, lab11 // Это будет выполнено в функции start() после регистрации плагинов // 4. Регистрация статических файлов будет выполнена в функции start() // 5. Дополнительный маршрут для проверки работоспособности fastify.get('/health', async (request, reply) => { return { status: 'ok', timestamp: new Date().toISOString(), version: '1.0.0' }; }); // 6. Обработка 404 для не найденных маршрутов fastify.setNotFoundHandler((request, reply) => { // Если это запрос к статическому файлу (HTML, CSS, JS и т.д.), не возвращаем JSON const url = request.url; const isStaticFile = /\.(html|css|js|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/i.test(url); if (isStaticFile) { reply.code(404).send('File not found'); } else { reply .code(404) .header('Content-Type', 'application/json; charset=utf-8') .send({ error: 'Маршрут не найден', path: request.url, method: request.method, timestamp: new Date().toISOString() }); } }); // 7. Обработка ошибок сервера fastify.setErrorHandler((error, request, reply) => { fastify.log.error('Необработанная ошибка:', error); reply .code(500) .header('Content-Type', 'application/json; charset=utf-8') .send({ error: 'Внутренняя ошибка сервера', message: error.message, stack: process.env.NODE_ENV === 'development' ? error.stack : undefined, timestamp: new Date().toISOString() }); }); // 8. Запуск сервера const start = async () => { try { // Регистрируем плагины await setupPlugins(); // Регистрируем маршруты для lab7, lab8, lab9, lab10, lab11 for (const labNumber of [7, 8, 9, 10, 11]) { await registerLabRoutes(labNumber); } // Регистрируем статические файлы (ПОСЛЕ API маршрутов) await fastify.register(FastifyStatic, { root: path.join(__dirname, '..', 'public'), prefix: '/', index: ['index.html'], decorateReply: false, redirect: true, wildcard: true }); // Проверяем подключение к БД перед стартом await fastify.ready(); // Проверяем подключение к БД и инициализируем схему lab11 try { const client = await fastify.pg.connect(); // Инициализация схемы lab11 try { // Создаем схему await client.query('CREATE SCHEMA IF NOT EXISTS lab11'); // Создаем таблицу roles await client.query(` CREATE TABLE IF NOT EXISTS lab11.roles ( id SERIAL PRIMARY KEY, name TEXT UNIQUE NOT NULL ) `); // Вставляем базовые роли await client.query(` INSERT INTO lab11.roles (name) VALUES ('user') ON CONFLICT (name) DO NOTHING `); await client.query(` INSERT INTO lab11.roles (name) VALUES ('admin') ON CONFLICT (name) DO NOTHING `); // Создаем таблицу users await client.query(` CREATE TABLE IF NOT EXISTS lab11.users ( id SERIAL PRIMARY KEY, login TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, role_id INT NOT NULL REFERENCES lab11.roles(id), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ) `); // Создаем временного пользователя admin (если его нет) await client.query(` INSERT INTO lab11.users (login, password_hash, role_id) SELECT 'admin', 'TEMP', r.id FROM lab11.roles r WHERE r.name = 'admin' ON CONFLICT (login) DO NOTHING `); fastify.log.info('Схема lab11 инициализирована'); } catch (initErr) { fastify.log.warn('Ошибка инициализации схемы lab11:', initErr.message); } client.release(); fastify.log.info('Подключение к базе данных успешно'); } catch (dbErr) { fastify.log.warn('Не удалось подключиться к БД, но сервер продолжит работу:', dbErr.message); } const address = await fastify.listen({ port: parseInt(process.env.PORT || '3000', 10), host: '0.0.0.0' }); fastify.log.info(`Сервер запущен на ${address}`); fastify.log.info(`База данных: ${process.env.DATABASE_URL || 'не настроена'}`); } catch (err) { fastify.log.error('Ошибка запуска сервера:', { message: err.message, stack: err.stack, code: err.code, errno: err.errno, syscall: err.syscall }); console.error('Полная ошибка:', err); process.exit(1); } }; start(); // Экспорт для использования в тестах или других модулях export default fastify;