hfs
Version:
HTTP File Server
94 lines (93 loc) • 4.05 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = __importDefault(require("lodash"));
const consoleLog_1 = require("./consoleLog");
const cross_1 = require("./cross");
const misc_1 = require("./misc");
const events_1 = __importDefault(require("./events"));
const log_1 = require("./log");
const promises_1 = require("fs/promises");
const SendList_1 = require("./SendList");
const serveFile_1 = require("./serveFile");
const ips_1 = require("./ips");
const connections_1 = require("./connections");
exports.default = {
async get_log_info() {
const current = Object.fromEntries(await Promise.all(log_1.loggers.map(async (x) => [x.name, await (0, promises_1.stat)(x.path).then(s => s.size, () => 0)])));
return { current, rotated: await (0, log_1.getRotatedFiles)() };
},
async get_log_file({ file = 'log', range = '' }, ctx) {
const log = lodash_1.default.find(log_1.loggers, { name: file });
if (!log)
throw cross_1.HTTP_NOT_FOUND;
if (!log.path)
throw cross_1.HTTP_NOT_ACCEPTABLE;
(0, serveFile_1.forceDownload)(ctx, log.path);
if (range)
ctx.request.header.range = `bytes=${range}`;
if (ctx.method === 'POST') // this would cause method_not_allowed
ctx.method = 'GET';
await (0, serveFile_1.serveFile)(ctx, log.path);
return null;
},
get_log({ file = 'log' }, ctx) {
const files = file.split('|'); // potentially more then one
return new SendList_1.SendListReadable({
bufferTime: 10,
async doAtStart(list) {
if (file === 'disconnections') {
for (const x of connections_1.disconnectionsLog)
list.add(x);
ctx.res.once('close', events_1.default.on('disconnection', x => list.add(x)));
return list.ready();
}
if (file === 'ips') {
for await (const [k, v] of ips_1.ips.iterator())
list.add({ ip: k, ...v });
return list.ready();
}
if (file === 'console') {
for (const chunk of lodash_1.default.chunk(consoleLog_1.consoleLog, 1000)) { // avoid occupying the thread too long
for (const x of chunk)
list.add(x);
await (0, cross_1.wait)(0);
}
ctx.res.once('close', events_1.default.on('console', x => list.add(x)));
return list.ready();
}
// for other logs we only provide updates. Use get_log_file to download past content
if (lodash_1.default.some(files, x => !lodash_1.default.find(log_1.loggers, { name: x })))
return list.error(cross_1.HTTP_NOT_FOUND, true);
list.ready();
// unsubscribe when connection is interrupted
ctx.res.once('close', events_1.default.on(files, x => list.add(Object.assign(lodash_1.default.pick(x.ctx, ['ip', 'method', 'status']), x, { ctx: undefined }))));
}
});
},
async delete_ips({ ip, ts }) {
(0, misc_1.apiAssertTypes)({ string_undefined: { ip, ts } });
if (ip) {
if (!ips_1.ips.has(ip))
throw cross_1.HTTP_NOT_FOUND;
ips_1.ips.del(ip);
return {};
}
if (ts) {
ts = new Date(ts);
let n = 0;
for await (const [k, rec] of ips_1.ips.iterator())
if (rec.ts <= ts) {
ips_1.ips.del(k);
++n;
}
return { n };
}
throw cross_1.HTTP_BAD_REQUEST;
},
reset_ips() {
return ips_1.ips.clear();
},
};
;