@opengis/fastify-table
Version:
core-plugins
98 lines (76 loc) • 3.05 kB
JavaScript
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;
}