Holly
5e271af9c9
As we take control of the request at this point and don't hand the control back, we never hit the logger line on the next hook.
149 lines
No EOL
4.3 KiB
TypeScript
149 lines
No EOL
4.3 KiB
TypeScript
import Fastify, { type FastifyReply, type FastifyRequest } from "fastify";
|
|
import FastifyFormBody from "@fastify/formbody";
|
|
import FastifyMultipart from "@fastify/multipart";
|
|
import FastifyCookie from "@fastify/cookie";
|
|
import FastifyView from "@fastify/view";
|
|
import FastifyStatic from "@fastify/static";
|
|
import Config from "./objects/Config";
|
|
import EJS from "ejs";
|
|
import { Console } from "hsconsole";
|
|
import Controller from "./controllers/Controller";
|
|
import HomeController from "./controllers/HomeController";
|
|
import Database from "./objects/Database";
|
|
import { join } from "path";
|
|
import AccountController from "./controllers/AccountController";
|
|
import { magenta, blue, cyan, green, red } from "dyetty";
|
|
import ConsoleUtility from "./utilities/ConsoleUtility";
|
|
import HashFS from "./objects/HashFS";
|
|
import FunkyArray from "funky-array";
|
|
import MediaService from "./services/MediaService";
|
|
import Media from "./entities/Media";
|
|
import HeaderUtility from "./utilities/HeaderUtility";
|
|
import { createReadStream } from "fs";
|
|
|
|
Console.customHeader(`EUS server started at ${new Date()}`);
|
|
|
|
const fastify = Fastify({
|
|
logger: false
|
|
});
|
|
|
|
fastify.register(FastifyView, {
|
|
engine: {
|
|
ejs: EJS
|
|
}
|
|
});
|
|
|
|
fastify.register(FastifyFormBody);
|
|
|
|
fastify.register(FastifyMultipart, {
|
|
limits: {
|
|
files: 1,
|
|
fileSize: 104857600
|
|
}
|
|
});
|
|
|
|
fastify.register(FastifyCookie, {
|
|
secret: Config.session.secret,
|
|
parseOptions: {
|
|
path: "/",
|
|
secure: true
|
|
}
|
|
});
|
|
|
|
fastify.register(FastifyStatic, {
|
|
root: join(__dirname, "wwwroot"),
|
|
preCompressed: true,
|
|
decorateReply: false,
|
|
redirect: false
|
|
});
|
|
|
|
function printReqInfo(req: FastifyRequest, res: FastifyReply) {
|
|
// @ts-ignore
|
|
Console.printInfo(`[ ${req.logType} ] [ ${req.method.toUpperCase()} ] [ ${ConsoleUtility.StatusColor(res.statusCode)} ] [ ${blue(`${Date.now() - req.startTime}ms`)} ] > ${req.url}`);
|
|
}
|
|
|
|
const hashLookupCache = new FunkyArray<string, Media>();
|
|
fastify.addHook("preHandler", (req, res, done) => {
|
|
(async () => {
|
|
// @ts-ignore
|
|
req.startTime = Date.now();
|
|
|
|
// * Take usual controller path if this path is registered.
|
|
if (Controller.RegisteredPaths.includes(req.url)) {
|
|
// @ts-ignore
|
|
req.logType = cyan("CONTROLLER");
|
|
HeaderUtility.AddBakedHeaders(res);
|
|
return done();
|
|
} else {
|
|
const urlParts = req.url.split("/");
|
|
if (urlParts.length === 2 && urlParts[1].length <= 16) {
|
|
let media = hashLookupCache.get(urlParts[1]) ?? null;
|
|
if (!media) {
|
|
media = await MediaService.GetByTag(urlParts[1]);
|
|
if (media) {
|
|
hashLookupCache.set(urlParts[1], media);
|
|
}
|
|
}
|
|
|
|
if (media) {
|
|
// @ts-ignore
|
|
req.logType = cyan("IMAGE");
|
|
const fileStore = HashFS.GetHashFSInstance("images");
|
|
const readStream = createReadStream(join(fileStore.path, fileStore.GetRelativePath(media.Hash)));
|
|
res.raw.writeHead(200, HeaderUtility.CombineHeaders({
|
|
"content-type": media.MediaType,
|
|
"content-length": media.FileSize,
|
|
}));
|
|
readStream.pipe(res.raw);
|
|
|
|
printReqInfo(req, res);
|
|
return;
|
|
}
|
|
} else {
|
|
HeaderUtility.AddBakedHeaders(res);
|
|
}
|
|
|
|
// @ts-ignore
|
|
req.logType = magenta("STATIC");
|
|
}
|
|
|
|
return done();
|
|
})();
|
|
});
|
|
|
|
fastify.addHook("onSend", (req, res, _payload, done) => {
|
|
printReqInfo(req, res);
|
|
|
|
done();
|
|
});
|
|
|
|
fastify.setNotFoundHandler(async (_req, res) => {
|
|
|
|
return res.status(404).view("views/404.ejs");
|
|
});
|
|
|
|
HashFS.STARTUP_DIR = __dirname;
|
|
new HashFS("images");
|
|
|
|
if (Config.database.enabled) {
|
|
new Database(Config.database.address, Config.database.port, Config.database.username, Config.database.password, Config.database.name);
|
|
} else {
|
|
Console.printInfo(`[ ${red("DATABASE")} ] Database is disabled.`);
|
|
}
|
|
|
|
if (Config.controllers.enabled && Config.database.enabled) {
|
|
Controller.FastifyInstance = fastify;
|
|
new AccountController();
|
|
new HomeController();
|
|
} else {
|
|
Console.printInfo(`[ ${red("CONTROLLER")} ] Controllers are disabled${Config.controllers.enabled && !Config.database.enabled ? " because the database is disabled but required by the controllers." : "."} Server will operate in static mode only.`);
|
|
}
|
|
|
|
fastify.listen({ port: Config.hosts.webPort, host: Config.hosts.webHost }, (err, address) => {
|
|
if (err) {
|
|
Console.printError(`Error occured while spinning up fastify:\n${err}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
Console.printInfo(`[ ${green("MAIN")} ] Listening at ${address.replace("0.0.0.0", "localhost").replace("127.0.0.1", "localhost")}`);
|
|
}); |