/
aurora
/
test
Обзор
Документация
Войти
/
aurora
/
test
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
01_week/00_node/solution_2.js
246 строк
7 KB
auroraptor
refactoring
22 июн 2024, 11:22
22 июн 2024, 11:22
6295ff9
Код
Авторство
О чём код?
import http from "node:http"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath, URL } from "node:url"; import readline from "node:readline"; // Определяем директорию файла const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Функция для загрузки переменных из .env файла function loadEnv() { const envPath = path.join(__dirname, ".env"); if (fs.existsSync(envPath)) { const envContent = fs.readFileSync(envPath, "utf-8"); envContent.split("\n").forEach((line) => { const [key, value] = line.split("="); if (key && value) { process.env[key.trim()] = value.trim(); } }); } } // Загружаем переменные окружения loadEnv(); // Читаем переменные окружения const PORT = process.env.PORT || 3000; const BACKUP_FILE_PATH = process.env.BACKUP_FILE_PATH; // Хэндлеры маршрутов const IMAGES_PATH = path.join(__dirname, "images"); const STATIC_IMAGES_PATH = "/static/images"; const GET_FILM_BY_ID_PATH = "/api/v1/movie"; const SEARCH_FILMS_BY_TITLE_PATH = "/api/v1/search"; // Создаем директорию для изображений, если она не существует if (!fs.existsSync(IMAGES_PATH)) { fs.mkdirSync(IMAGES_PATH); } const OUTPUT_FILE_PATH = path.join(__dirname, "output"); if (!fs.existsSync(OUTPUT_FILE_PATH)) { fs.mkdirSync(OUTPUT_FILE_PATH); } // Индекс для быстрого поиска по заголовкам const titleIndex = {}; // Функция для чтения файла в режиме потока и парсинга данных const readBackupFile = () => { return new Promise((resolve, reject) => { const readStream = fs.createReadStream(BACKUP_FILE_PATH, { encoding: "utf8" }); const rl = readline.createInterface({ input: readStream }); rl.on("line", (line) => { try { const parsedLine = JSON.parse(line); if (parsedLine.id) { // Построение индекса для поиска по заголовкам const title = parsedLine.title.toLowerCase(); if (!titleIndex[title]) { titleIndex[title] = []; } titleIndex[title].push(parsedLine.id); // Сохранение изображений из поля img if (parsedLine.img) { const imagePath = path.join(IMAGES_PATH, `${parsedLine.id}.jpeg`); const buffer = Buffer.from(parsedLine.img, "base64"); fs.writeFileSync(imagePath, buffer); } // Сохранение данных на диск const dataPath = path.join(__dirname, 'output', `${parsedLine.id}.json`); fs.writeFileSync(dataPath, JSON.stringify(parsedLine)); } } catch (error) { console.error(`Error parsing line: ${line}`, error); } }); rl.on("close", () => { resolve(); }); rl.on("error", (error) => { reject(error); }); }); }; // Универсальные обработчики ошибок const handleBadRequest = (res, message = "Bad Request") => { res.statusCode = 400; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify({ error: message })); }; const handleNotFound = (res, message = "Not Found") => { res.statusCode = 404; res.setHeader("Content-Type", "text/plain"); res.end(message); }; const handlePing = (req, res) => { res.statusCode = 200; res.end("pong"); }; const handleEcho = (req, res) => { let body = ""; req.on("data", (chunk) => { body += chunk.toString(); }); req.on("end", () => { try { const parsedBody = JSON.parse(body.trim()); const message = parsedBody ?? "Тут должно было быть сообщение, но что-то пошло не так. 😔"; res.statusCode = 200; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify(message)); } catch (error) { handleBadRequest(res, "Invalid JSON format"); } }); }; const handleGetById = (req, res) => { const id = req.url.split(`${GET_FILM_BY_ID_PATH}/`)[1]; if (!id) { handleBadRequest(res, "ID parameter is required"); return; } const dataPath = path.join(__dirname, 'output', `${id}.json`); if (fs.existsSync(dataPath)) { const data = fs.readFileSync(dataPath, 'utf8'); const { id, title, description, genre, release_year } = JSON.parse(data.trim()); res.statusCode = 200; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify({ id, title, description, genre, release_year })); } else { handleNotFound(res, `Film with ID: ${id} not found`); } }; const handleSearchFilmsByTitle = (req, res) => { const url = new URL(req.url, `http://${req.headers.host}`); const titleQuery = url.searchParams.get("title"); const page = parseInt(url.searchParams.get("page"), 10); const resultsPerPage = 10; const regex = new RegExp(titleQuery, "i"); const matchedTitles = Object.keys(titleIndex).filter((title) => regex.test(title) ); const matchedIds = matchedTitles.map((title) => titleIndex[title]).flat(); const paginatedIds = matchedIds.slice( Math.max(page - 1, 0) * resultsPerPage, Math.max(page, 1) * resultsPerPage ); const paginatedResults = paginatedIds.map(id => { const dataPath = path.join(__dirname, 'output', `${id}.json`); return JSON.parse(fs.readFileSync(dataPath, 'utf8')); }); res.statusCode = 200; res.setHeader("Content-Type", "application/json"); res.end( JSON.stringify({ search_result: paginatedResults.map( ({ id, title, description, genre, release_year }) => ({ id, title, description, genre, release_year, }) ), }) ); }; const handleStaticImages = (req, res) => { const id = req.url.split(`${STATIC_IMAGES_PATH}/`)[1]; const imagePath = path.join(IMAGES_PATH, `${id}`); fs.readFile(imagePath, (err, data) => { if (err) { handleNotFound(res, "Image not found"); } else { res.statusCode = 200; res.setHeader("Content-Type", "image/jpeg"); res.end(data); } }); }; // Читаем файл при запуске сервера readBackupFile() .then(() => { console.log("Backup file read successfully"); // Запуск сервера const server = http.createServer((req, res) => { if (req.url === "/ping" && req.method === "GET") { handlePing(req, res); } else if (req.url === "/echo" && req.method === "POST") { handleEcho(req, res); } else if ( req.url.startsWith(GET_FILM_BY_ID_PATH) && req.method === "GET" ) { handleGetById(req, res); } else if ( req.url.startsWith(SEARCH_FILMS_BY_TITLE_PATH) && req.method === "GET" ) { handleSearchFilmsByTitle(req, res); } else if ( req.url.startsWith(STATIC_IMAGES_PATH) && req.method === "GET" ) { handleStaticImages(req, res); } else { handleNotFound(res, "Page Not Found"); } }); server.listen(PORT, () => { const address = server.address(); const host = address.address === "::" ? "localhost" : address.address; const port = address.port; console.log(`Server running at http://${host}:${port}/`); }); }) .catch((error) => { console.error("Error reading backup file:", error); });