hfs
Version:
HTTP File Server
87 lines (86 loc) • 4.53 kB
JavaScript
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.app = void 0;
const koa_1 = __importDefault(require("koa"));
const koa_mount_1 = __importDefault(require("koa-mount"));
require("./consoleLog");
const apiMiddleware_1 = require("./apiMiddleware");
const const_1 = require("./const");
const frontEndApis_1 = require("./frontEndApis");
const log_1 = require("./log");
const plugins_1 = require("./plugins");
const throttler_1 = require("./throttler");
const middlewares_1 = require("./middlewares");
const serveGuiAndSharedFiles_1 = require("./serveGuiAndSharedFiles");
require("./listen");
require("./commands");
const adminApis_1 = require("./adminApis");
const config_1 = require("./config");
const assert_1 = require("assert");
const lodash_1 = __importDefault(require("lodash"));
const misc_1 = require("./misc");
const selfCheck_1 = require("./selfCheck");
const acme_1 = require("./acme");
require("./geo");
const geo_1 = require("./geo");
const roots_1 = require("./roots");
const events_1 = __importDefault(require("./events"));
const ips_1 = require("./ips");
(0, assert_1.ok)(lodash_1.default.intersection(Object.keys(frontEndApis_1.frontEndApis), Object.keys(adminApis_1.adminApis)).length === 0); // they share same endpoints, don't clash
process.title = 'HFS ' + const_1.VERSION;
const keys = ((_a = process.env.COOKIE_SIGN_KEYS) === null || _a === void 0 ? void 0 : _a.split(','))
|| [(0, misc_1.randomId)(30)]; // randomness at start gives some extra security, btu also invalidates existing sessions
exports.app = new koa_1.default({ keys });
exports.app.use(middlewares_1.sessionMiddleware)
.use(selfCheck_1.selfCheckMiddleware)
.use(acme_1.acmeMiddleware)
.use(middlewares_1.someSecurity)
.use(middlewares_1.prepareState)
.use(geo_1.geoFilter)
.use(ips_1.trackIpsMw)
.use(middlewares_1.gzipper)
.use(middlewares_1.paramsDecoder) // must be done before plugins, so they can manipulate params
.use(middlewares_1.headRequests)
.use(roots_1.rootsMiddleware)
.use(log_1.logMw)
.use(throttler_1.throttler)
.use(plugins_1.pluginsMiddleware)
.use((0, koa_mount_1.default)(const_1.API_URI, (0, apiMiddleware_1.apiMiddleware)({ ...frontEndApis_1.frontEndApis, ...adminApis_1.adminApis })))
.use(serveGuiAndSharedFiles_1.serveGuiAndSharedFiles)
.on('error', errorHandler);
events_1.default.emit('app', exports.app);
function errorHandler(err) {
const { code } = err;
if (const_1.DEV && code === 'ENOENT' && err.path.endsWith('sockjs-node'))
return; // spam out dev stuff
if (code === 'ECANCELED' || code === 'ECONNRESET' || code === 'ECONNABORTED' || code === 'EPIPE'
|| code === 'ERR_STREAM_WRITE_AFTER_END' // happens disconnecting uploads, don't care
|| code === 'ERR_STREAM_PREMATURE_CLOSE' // happens when many files are sent (not locally), but I checked that the files are written completely. Introduced after node18.5.0 and is thrown by pipeline() used by PUT method handler.
|| code === 'HPE_INVALID_METHOD' // cannot serve you like that
|| code === 'HPE_INVALID_EOF_STATE')
return; // someone interrupted, don't care
console.error('server error', err);
}
process.on('uncaughtException', (err) => {
if (err.syscall !== 'watch' && err.code !== 'ECONNRESET' && err.code !== 'EIO') // EIO seems to happen when the terminal is closed
try {
console.error("uncaught:", err);
}
catch (_a) { } // in case we are writing to a closed terminal, we may throw with "write eio at afterwritedispatched", causing an infinite loop
});
// this warning is scaring users, and has been removed in node 20.12.0 https://github.com/nodejs/node/pull/51204
const original = process.emitWarning;
process.emitWarning = warn => String(warn).startsWith('An error event has already been emitted') || original.call(process, warn);
(0, config_1.defineConfig)('proxies', 0).sub(n => {
exports.app.proxy = n > 0;
exports.app.maxIpsCount = n;
});
exports.app.context.isAborted = function () {
return this.res.destroyed || this.req.aborted; // investigate: "aborted" is deprecated, but "destroyed" will cause failure of some tests
};
;