diff --git a/.gitignore b/.gitignore index 40b878d..8a67c40 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules/ \ No newline at end of file +node_modules/ +config.yml \ No newline at end of file diff --git a/index.js b/index.js index 3b78f76..5b5af9f 100644 --- a/index.js +++ b/index.js @@ -1,21 +1,38 @@ +const fs = require("fs"); +const path = require("path"); +const yaml = require("js-yaml"); const express = require("express"); -const http = require("http"); +const http = require("http"); const { Server } = require("socket.io"); -const cors = require("cors"); +const cors = require("cors"); const axios = require("axios"); -const app = express(); -const server = http.createServer(app); +// ─── Config ─────────────────────────────────────────────────────────────────── +const configPath = path.join(__dirname, "config.yml"); +const config = yaml.load(fs.readFileSync(configPath, "utf8")); -const io = new Server(server, { +const PORT = config.server?.port || 4000; +const HOSTS = config.targets?.hosts || ["http://127.0.0.1:7088"]; +const ENDPOINTS = config.targets?.endpoints || []; +const TIMEOUT = config.targets?.timeout || 120_000; + +console.log(`[config] loaded from ${configPath}`); +console.log(`[config] hosts (${HOSTS.length}):`, HOSTS); +console.log(`[config] endpoints:`, ENDPOINTS); + +// ─── Express + Socket.io ────────────────────────────────────────────────────── +const app = express(); +const server = http.createServer(app); +const io = new Server(server, { cors: { origin: "*", methods: ["GET", "POST"] }, }); app.use(cors()); app.use(express.json()); +// ─── POST /api/parallel-fetch ───────────────────────────────────────────────── app.post("/api/parallel-fetch", async (req, res) => { - const { socketId, url, timeout = 120_000 } = req.body; + const { socketId, url, timeout = TIMEOUT } = req.body; if (!socketId || !url) { return res.status(400).json({ error: "socketId and url are required" }); @@ -28,19 +45,15 @@ app.post("/api/parallel-fetch", async (req, res) => { res.json({ status: "started" }); - const baseUrl = "http://127.0.0.1:7088"; - const endpoints = [ - "/testmontools/curl", - "/testmontools/traceroute", - "/testmontools/ping", - ]; + const tasks = HOSTS.flatMap((host) => + ENDPOINTS.map((endpoint) => ({ host, endpoint })) + ); - // Сообщаем клиенту сколько запросов будет - socket.emit("batch:start", { url, total: endpoints.length }); + socket.emit("batch:start", { url, total: tasks.length }); - const localTasks = endpoints.map((endpoint) => { - const fullUrl = baseUrl + endpoint; - const start = Date.now(); + const promises = tasks.map(({ host, endpoint }) => { + const fullUrl = host + endpoint; + const start = Date.now(); return axios({ method: "POST", @@ -51,11 +64,9 @@ app.post("/api/parallel-fetch", async (req, res) => { }) .then((response) => { const elapsed = Date.now() - start; - console.log(`[OK] ${endpoint} (${elapsed}ms)`); - console.log("data:", response.data); - + console.log(`[OK] ${host} ${endpoint} (${elapsed}ms)`); socket.emit("tool:response", { - endpoint, + host, endpoint, ok: true, status: response.status, data: response.data, @@ -64,10 +75,9 @@ app.post("/api/parallel-fetch", async (req, res) => { }) .catch((err) => { const elapsed = Date.now() - start; - console.log(`[ERROR] ${endpoint} (${elapsed}ms) — ${err.message}`); - + console.log(`[ERROR] ${host} ${endpoint} (${elapsed}ms) — ${err.message}`); socket.emit("tool:error", { - endpoint, + host, endpoint, ok: false, error: err.message, code: err.code || null, @@ -76,19 +86,26 @@ app.post("/api/parallel-fetch", async (req, res) => { }); }); - // Когда все завершились — шлём финальное событие - Promise.allSettled(localTasks).then(() => { + Promise.allSettled(promises).then(() => { console.log("=== ALL DONE ==="); - socket.emit("batch:done", { url, total: endpoints.length }); + socket.emit("batch:done", { url, total: tasks.length }); }); }); -app.get("/health", (_req, res) => res.json({ ok: true })); +// ─── Health ─────────────────────────────────────────────────────────────────── +app.get("/health", (_req, res) => + res.json({ ok: true, hosts: HOSTS, endpoints: ENDPOINTS }) +); +// ─── Socket lifecycle ───────────────────────────────────────────────────────── io.on("connection", (socket) => { - console.log(`[socket] connected ${socket.id}`); - socket.on("disconnect", () => console.log(`[socket] disconnected ${socket.id}`)); + console.log(`[socket] connected ${socket.id}`); + socket.on("disconnect", () => + console.log(`[socket] disconnected ${socket.id}`) + ); }); -const PORT = process.env.PORT || 4000; -server.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`)); \ No newline at end of file +// ─── Start ──────────────────────────────────────────────────────────────────── +server.listen(PORT, () => + console.log(`Server running on http://localhost:${PORT}`) +); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 947e8b2..4a75023 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "axios": "^1.6.0", "cors": "^2.8.5", "express": "^4.18.2", + "js-yaml": "^4.1.1", "socket.io": "^4.6.1" }, "devDependencies": { @@ -103,6 +104,11 @@ "node": ">= 8" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -853,6 +859,17 @@ "node": ">=0.12.0" } }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/package.json b/package.json index f6e3671..f56e564 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "axios": "^1.6.0", "cors": "^2.8.5", "express": "^4.18.2", - "socket.io": "^4.6.1" + "socket.io": "^4.6.1", + "js-yaml": "^4.1.1" }, "devDependencies": { "nodemon": "^3.0.2"