forked from f0ck/f0ckv2
86 lines
2.7 KiB
JavaScript
86 lines
2.7 KiB
JavaScript
import fs from "fs";
|
|
import path from "path";
|
|
|
|
export default new class Router {
|
|
#mimes;
|
|
constructor() {
|
|
this.routes = new Map();
|
|
};
|
|
route(method, args) {
|
|
this.routes.set(args[0], { method: method, f: args[1] });
|
|
console.info("route set", method, args[0]);
|
|
};
|
|
get() {
|
|
this.route("GET", arguments);
|
|
};
|
|
post() {
|
|
this.route("POST", arguments);
|
|
};
|
|
async static({ dir = path.resolve() + "/public", route = /^\/public/ }) {
|
|
if(!this.#mimes) {
|
|
this.#mimes = new Map();
|
|
(await fs.promises.readFile("/etc/mime.types", "utf-8"))
|
|
.split("\n")
|
|
.filter(e => !e.startsWith("#") && e)
|
|
.map(e => e.split(/\s{2,}/))
|
|
.filter(e => e.length > 1)
|
|
.forEach(m => m[1].split(" ").forEach(ext => this.#mimes.set(ext, m[0])));
|
|
}
|
|
|
|
this.get(route, async (req, res) => {
|
|
try {
|
|
const mime = this.#mimes.get(req.url.path.split(".").pop());
|
|
const file = path.join(dir, req.url.path.replace(route, ""));
|
|
let stat;
|
|
try {
|
|
stat = await fs.promises.stat(file);
|
|
} catch {
|
|
return res.reply({
|
|
code: 404,
|
|
body: "404 - file not found."
|
|
});
|
|
}
|
|
|
|
if(!mime.startsWith("video") && !mime.startsWith("audio")) {
|
|
return res.reply({
|
|
type: this.#mimes.get(req.url.path.split(".").pop()).toLowerCase(),
|
|
body: await fs.promises.readFile(path.join(dir, req.url.path.replace(route, "")))
|
|
});
|
|
}
|
|
|
|
if(req.headers.range) {
|
|
const parts = req.headers.range.replace(/bytes=/, "").split("-");
|
|
const start = parseInt(parts[0], 10);
|
|
const end = parts[1] ? parseInt(parts[1], 10) : stat.size - 1;
|
|
res.writeHead(206, {
|
|
"Content-Range": `bytes ${start}-${end}/${stat.size}`,
|
|
"Accept-Ranges": "bytes",
|
|
"Content-Length": (end - start) + 1,
|
|
"Content-Type": mime,
|
|
});
|
|
const stream = fs.createReadStream(file, { start: start, end: end })
|
|
.on("open", () => stream.pipe(res))
|
|
.on("error", err => res.end(err));
|
|
}
|
|
else {
|
|
res.writeHead(200, {
|
|
"Content-Length": stat.size,
|
|
"Content-Type": mime,
|
|
});
|
|
fs.createReadStream(file).pipe(res);
|
|
}
|
|
} catch(err) {
|
|
console.error(err);
|
|
return res.reply({
|
|
code: 500,
|
|
body: "500 - f0ck hat keinen b0ck"
|
|
});
|
|
}
|
|
});
|
|
};
|
|
};
|
|
|
|
Map.prototype.getRoute = function(path, method, tmp) {
|
|
return (!(tmp = [...this.entries()].filter(r => ( r[0] === path || r[0].exec?.(path) ) && r[1].method.includes(method) )[0])) ? false : tmp[1].f;
|
|
};
|