From 81afe5052627ed54a274c6b87b77256270a8fe84 Mon Sep 17 00:00:00 2001 From: Holly <onlinegamer748@gmail.com> Date: Thu, 27 Mar 2025 00:02:43 +0000 Subject: [PATCH] experimental media domain + temp allow node while bun has node:http issues --- bun.lockb | Bin 72259 -> 72764 bytes entities/Domain.ts | 1 + index.ts | 108 +++++++++++++++++++++++++++---------- package.json | 1 + repos/DomainRepo.ts | 12 +++++ services/DomainService.ts | 18 +++++++ utilities/HeaderUtility.ts | 12 ++++- 7 files changed, 123 insertions(+), 29 deletions(-) diff --git a/bun.lockb b/bun.lockb index db143bc10c488b8637405afab80f1450e889303d..97943347ccf62f815a6da10bd2120f99701bbf34 100755 GIT binary patch delta 8880 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 HLg+sLNt+vm delta 8532 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 diff --git a/entities/Domain.ts b/entities/Domain.ts index 19bc8fb..15c840b 100644 --- a/entities/Domain.ts +++ b/entities/Domain.ts @@ -6,6 +6,7 @@ export default class Domain { return this.HasHttps ? "Yes" : "No"; } public Domain: string = ""; + public MediaDomain: string = ""; public Active: boolean = false; public get ActiveString() { return this.Active ? "Yes" : "No"; diff --git a/index.ts b/index.ts index bd37930..d9a3bb1 100644 --- a/index.ts +++ b/index.ts @@ -1,7 +1,10 @@ -if (!process.versions.bun) { - console.log("EUS is only designed to run on Bun, sorry!"); - process.exit(1); -} +// HSNOTE: It is designed to be used with bun but there is an issue with +// bun's implementation of node:http so i've temp allowed this to +// run with node again. very disapointed. +// if (!process.versions.bun) { +// console.log("EUS is only designed to run on Bun, sorry!"); +// process.exit(1); +// } import Fastify, { type FastifyReply, type FastifyRequest } from "fastify"; import FastifyFormBody from "@fastify/formbody"; @@ -9,6 +12,7 @@ import FastifyMultipart from "@fastify/multipart"; import FastifyCookie from "@fastify/cookie"; import FastifyView from "@fastify/view"; import FastifyStatic from "@fastify/static"; +//import FastifySend from "@fastify/send"; import Config from "./objects/Config"; import EJS from "ejs"; import { Console } from "hsconsole"; @@ -27,6 +31,7 @@ import HeaderUtility from "./utilities/HeaderUtility"; import { createReadStream } from "fs"; import ApiController from "./controllers/ApiController"; import UploadController from "./controllers/UploadController"; +import DomainService from "./services/DomainService"; Console.customHeader(`EUS server started at ${new Date()}`); @@ -82,32 +87,40 @@ fastify.addHook("preHandler", (req, res, done) => { 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); + const domain = await DomainService.LoadDomainByHost(req.headers.host ?? ""); + if (domain) { + 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("MEDIA"); - 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); + if (media) { + // @ts-ignore + /*req.logType = "REDIRECT_TO_MEDIA"; + res.redirect(`${domain.HasHttps ? "https" : "http"}://${domain.MediaDomain}/${media.MediaTag}`); + return;*/ - printReqInfo(req, res); - return; + // @ts-ignore + req.logType = cyan("MEDIA"); + 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); } - } else { - HeaderUtility.AddBakedHeaders(res); } // @ts-ignore @@ -119,7 +132,10 @@ fastify.addHook("preHandler", (req, res, done) => { }); fastify.addHook("onSend", (req, res, _payload, done) => { - printReqInfo(req, res); + // @ts-ignore + if (req.logType !== "REDIRECT_TO_MEDIA") { + printReqInfo(req, res); + } done(); }); @@ -158,4 +174,40 @@ fastify.listen({ port: Config.hosts.webPort, host: Config.hosts.webHost }, (err, Console.printWarn(`[ ${green("MAIN")} ] The EUS rewrite is currently beta software, use at your own risk!`); Console.printInfo(`[ ${green("MAIN")} ] Listening at ${address.replace("0.0.0.0", "localhost").replace("127.0.0.1", "localhost")}`); -}); \ No newline at end of file +}); + +/*const mediaServer = createServer(async (req, res) => { + const startTime = Date.now(); + 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) { + const fileStore = HashFS.GetHashFSInstance("images"); + + const { statusCode, headers, stream } = await FastifySend(req, fileStore.GetRelativePath(media.Hash), { root: fileStore.path }); + headers["content-type"] = media.MediaType; + res.writeHead(statusCode, HeaderUtility.CombineHeaders(headers)); + stream.pipe(res); + + Console.printInfo(`[ ${cyan("MEDIA")} ] [ ${req.method?.toUpperCase()} ] [ ${ConsoleUtility.StatusColor(res.statusCode)} ] [ ${blue(`${Date.now() - startTime}ms`)} ] > ${req.url}`); + return; + } else { + + } + } + + res.statusCode = 404; + res.write("EUS Media Server"); + return res.end(); +}); + +mediaServer.listen(Config.hosts.webPort + 1, () => { + Console.printInfo(`[ ${cyan("MEDIA")} ] Listening at http://localhost:${(Config.hosts.webPort + 1)}`); +});*/ \ No newline at end of file diff --git a/package.json b/package.json index 633b438..327570a 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@fastify/cookie": "^11.0.2", "@fastify/formbody": "^8.0.2", "@fastify/multipart": "^9.0.3", + "@fastify/send": "^4.0.0", "@fastify/static": "^8.1.1", "@fastify/view": "^11.0.0", "dyetty": "^1.0.1", diff --git a/repos/DomainRepo.ts b/repos/DomainRepo.ts index d9ad62c..4b9da3a 100644 --- a/repos/DomainRepo.ts +++ b/repos/DomainRepo.ts @@ -50,6 +50,17 @@ export default class DomainRepo { } } + public static async SelectByMediaDomain(domain: string) { + const dbDomain = await Database.Instance.query("SELECT * FROM Domain WHERE MediaDomain = ? AND IsDeleted = 0 LIMIT 1", [domain]); + if (dbDomain == null || dbDomain.length === 0) { + return null; + } else { + const domain = new Domain(); + PopulateDomainFromDB(domain, dbDomain[0]); + return domain; + } + } + public static async InsertUpdate(domain: Domain) { if (domain.Id === Number.MIN_VALUE) { domain.Id = (await Database.Instance.query("INSERT Domain (UserId, DomainId, FileName, MediaTag, MediaType, Hash, FileSize, CreatedByUserId, CreatedDatetime, LastModifiedByUserId, LastModifiedDatetime, DeletedByUserId, DeletedDatetime, IsDeleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING Id;", [ @@ -70,6 +81,7 @@ function PopulateDomainFromDB(domain: Domain, dbDomain: any) { domain.UserId = dbDomain.UserId; domain.HasHttps = dbDomain.HasHttps[0] === 1; domain.Domain = dbDomain.Domain; + domain.MediaDomain = dbDomain.MediaDomain; domain.Active = dbDomain.Active[0] === 1; domain.CreatedByUserId = dbDomain.CreatedByUserId; domain.CreatedDatetime = dbDomain.CreatedDatetime; diff --git a/services/DomainService.ts b/services/DomainService.ts index 356ee69..93a8236 100644 --- a/services/DomainService.ts +++ b/services/DomainService.ts @@ -10,4 +10,22 @@ export default abstract class DomainService { throw e; } } + + public static async LoadDomainByHost(host: string) { + try { + return await DomainRepo.SelectByDomain(host); + } catch (e) { + Console.printError(`EUS server service error:\n${e}`); + throw e; + } + } + + public static async LoadDomainByMediaHost(host: string) { + try { + return await DomainRepo.SelectByMediaDomain(host); + } catch (e) { + Console.printError(`EUS server service error:\n${e}`); + throw e; + } + } } \ No newline at end of file diff --git a/utilities/HeaderUtility.ts b/utilities/HeaderUtility.ts index 490130e..3f089d4 100644 --- a/utilities/HeaderUtility.ts +++ b/utilities/HeaderUtility.ts @@ -10,8 +10,11 @@ export default abstract class HeaderUtility { "Referrer-Policy": "strict-origin-when-cross-origin", "Content-Security-Policy": "block-all-mixed-content;frame-ancestors 'self'", "X-Frame-Options": "SAMEORIGIN", - "X-Content-Type-Options": "nosniff" + "X-Content-Type-Options": "nosniff", + "Connection": "keep-alive", + "Keep-Alive": "timeout=5" }; + public static BakedHeadersKeys = Object.keys(this.BakedHeaders); public static AddBakedHeaders(res: FastifyReply) { /*res.header("x-powered-by", "EUS"); @@ -26,6 +29,13 @@ export default abstract class HeaderUtility { res.headers(this.BakedHeaders); } + public static AddBakedHeadersExpress(res: any) { + for (const key of this.BakedHeadersKeys) { + // @ts-ignore + res.header(key, this.BakedHeaders[key]); + } + } + public static CombineHeaders(headers: any) { // for (const header of Object.keys(headers)) { // res.header(header, headers[header]);