UNPKG

@opengis/fastify-table

Version:

core-plugins

98 lines (76 loc) 3.05 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 './utils/checkUserAccess.js'; import getRootDir from './utils/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, { buffer: true }); return buffer; } if (query.full && isFile) { if (stat.size > 20 * 1000 * 1000) { return { message: 'file size > 20MB' }; } const buffer = await readFile(filepath, { buffer: true }); 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, { buffer: true }); 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.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; }