// 远程日志接收器 // 监听 HTTP 端口,接收日志内容推送(POST /log,JSON 或纯文本), // 按日期追加存入 received_logs/ 文件夹。日志内容直接传输,不做文件传输。 import { createServer } from "node:http"; import { mkdir, appendFile } from "fs/promises"; import { existsSync } from "fs"; import { resolve } from "path"; const PORT = parseInt(process.env.RECEIVER_PORT || "3200", 10); const LOG_DIR = resolve("received_logs"); function now(iso: string): string { return iso ? iso : new Date().toISOString(); } function fmtEntry(p: { level?: string; category?: string; message?: string; line?: string; ts?: string }): string { const ts = now(p.ts); const level = (p.level || "info").toUpperCase().padEnd(5); const category = p.category || "receiver"; const message = p.message !== undefined ? p.message : ""; return `[${ts}] [${level}] [${category}] ${message}`; } const server = createServer(async (req, res) => { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type"); if (req.method === "OPTIONS") { res.writeHead(204); res.end(); return; } const url = new URL(req.url || "/", `http://localhost:${PORT}`); if (req.method === "GET") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ status: "ok", name: "远程日志接收器", receivePath: "POST /log", port: PORT })); return; } if (req.method === "POST" && (url.pathname === "/log" || url.pathname === "/")) { let body = ""; try { for await (const c of req) body += c; } catch { res.writeHead(400); res.end("bad request"); return; } let entry: string; let level = "info"; let category = "receiver"; try { const json = JSON.parse(body); if (typeof json === "string") { entry = json; } else if (json.line) { entry = json.line; level = json.level || level; category = json.category || category; } else { entry = fmtEntry({ level: json.level, category: json.category, message: json.message, ts: json.ts }); level = json.level || level; category = json.category || category; } } catch { entry = fmtEntry({ level, category, message: body, ts: new Date().toISOString() }); } try { if (!existsSync(LOG_DIR)) await mkdir(LOG_DIR, { recursive: true }); const ts = new Date().toISOString().slice(0, 10); await appendFile(resolve(LOG_DIR, `received-${ts}.log`), entry + "\n", "utf-8"); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ ok: true })); } catch (e) { res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ ok: false, error: (e as any).message })); } return; } res.writeHead(404); res.end("Not Found"); }); server.listen(PORT, () => { console.log(`[remote_receiver] 远程日志接收器已启动: http://127.0.0.1:${PORT}/log (存入 ${LOG_DIR})`); });