UNPKG

@opengis/fastify-table

Version:

core-plugins

83 lines (82 loc) 3.29 kB
import path from "node:path"; import { lstat, readdir, readFile } from "node:fs/promises"; import { createReadStream, existsSync } from "node:fs"; import readline from "node:readline"; import checkUserAccess from "../../../plugins/logger/checkUserAccess.js"; import getRootDir from "../../../plugins/logger/getRootDir.js"; const limit = 200000; const rootDir = getRootDir(); /** * * @method GET * @summary API для перегляду логів * */ export default async function loggerFile(req, reply) { const { params = {}, user = {}, query = {}, originalUrl } = req; const access = checkUserAccess({ user, token: query.token }); if (access?.status !== 200) return reply.status(access.status).send(access.message); // absolute / relative path const filepath = path.join(rootDir, params["*"] || ""); if (!existsSync(filepath)) { return reply.status(404).send("file not exists"); } const stat = await lstat(filepath); const isFile = stat.isFile(); if (query.download && isFile) { const buffer = await readFile(filepath); return buffer; } if (query.full && isFile) { if (stat.size > 20 * 1000 * 1000) { return reply.status(400).send({ error: "file size > 20MB", code: 400 }); } const buffer = await readFile(filepath); return buffer; } if (isFile) { const ext = path.extname(filepath); const lines = await new Promise((resolve) => { const rl = readline.createInterface({ input: createReadStream(filepath, { start: stat.size > limit ? stat.size - limit : 0, }), }); const lines1 = []; rl.on("close", () => resolve(lines1)); rl.on("line", (line) => lines1.push(line)); }); if (ext === ".html") { const buffer = await readFile(filepath); reply.headers({ "Content-type": "text/html; charset=UTF-8" }); return buffer; } reply.headers({ "Content-type": "text/plain; charset=UTF-8" }); return stat.size > limit && lines.length > 1 ? lines.reverse().slice(0, -1).join("\n") : lines.reverse().join("\n"); } // dir const files = await readdir(filepath); if (query.dir) { return files.filter((el) => !["backup", "marker_icon", "error", "migration"].includes(el)); } const lstatsArr = await Promise.all(files.map(async (file) => [file, await lstat(path.join(filepath, file))])); const lstats = Object.fromEntries(lstatsArr); const relpaceable = query.token ? `?token=${query.token}` : ""; const relpath = query.token ? originalUrl.replace(relpaceable, "") : originalUrl; const message = (params["*"] ? '<a href="/logger-file/">...</a><br>' : "") + files .sort((a, b) => lstats[a].mtimeMs - lstats[b].mtimeMs) .map((file) => `<a href="${relpath}/${file}${relpaceable}">${file}</a> (${lstats[file].size} bytes)`) .join("</br>"); reply.headers({ "Content-Type": "text/html; charset=UTF-8", "Content-Security-Policy": "default-src 'none'", "X-Content-Type-Options": "nosniff", }); return message; }